#!/usr/bin/env python
# coding=UTF-8
import random
import logging
import json
import time
import datetime

import config
import dao

from nsq.http import nsqd
import redisco
from redisco.containers import List, Hash

def get_last_data(reader, bid, uid, data):
    user_info = Hash("%s_%s" % (bid, uid))
    rid = user_info['rid']
    if not rid:
        rid = data.get("rid", "")
    room = Hash("r:%s" % rid)
    game_type = room['game_type']
    if game_type == 'zzmj':
        tdh = ZZMaJiang(rid, bid)
    elif game_type == 'hzmj':
        tdh = HZMaJiang(rid, bid)
    elif game_type == 'csmj':
        tdh = CSMaJiang(rid, bid)
    elif game_type == 'pdk':
        tdh = PaoDeKuai(rid, bid)
    else:
        tdh = MaJiang(rid, bid)
    last_get_user = tdh.room['last_get_user']
    last_put_user = tdh.room['last_put_user']
    pubdata = {'act':'get_last_data', 'rid':rid, 'last_player':last_get_user, 'last_put_user':last_put_user}
    all_player_data = []
    l = List("r:%s:p" % rid)
    members = l.members
    for member in members:
        p = Player(member, bid, rid)
        player_data = p.get_data()
        eat_list = []
        eat_data_list = player_data['eat']
        for eat_data in eat_data_list:
            eat_list.append(eat_data.split(","))
        player_data['eat'] = eat_list
        if member != uid:
            player_data['current_card'] = ["*"] * len(player_data['current_card'])
            #player_data['dark_bar'] = ["*"] * len(player_data['dark_bar'])
        if game_type == 'pdk':
            del player_data['out_card']
            del player_data['dark_bar']
            del player_data['white_bar']
            del player_data['pair']
        player_data['status'] = 1
        all_player_data.append(player_data)
    tips = []
    dark_bar = []
    eat_card = []
    last_put_card = ''
    stop_pop_user = tdh.room['stop_pop_user']
    
    if game_type == 'pdk':
        tips = []
        if not last_put_user:
            last_put_user = stop_pop_user
        pubdata['last_player'] = stop_pop_user
        pubdata['last_put_user'] = last_put_user
        pubdata['put_type'] = ''
        pubdata['last_put_card'] = tdh.room['last_put_card'].split(",")
    else:
        if stop_pop_user == str(uid):
            tips = tdh.room['stop_pop_act'].split(",")
            if tips:
                p = Player(uid, bid, rid)
                current_card = p.current_card.members
                if 'dark_bar' in tips:
                    dark_bar = tdh.check_init_dark_bar(current_card)
                if "eat" in tips:
                    last_put_player = Player(last_put_user, bid, rid)
                    last_put_card = last_put_player.out_card.members[-1]
                    eat_card = tdh.get_eat_card(current_card, last_put_card)
        pubdata["eat_card"] = eat_card
        pubdata["dark_bar"] = dark_bar
        pubdata["left_card"] = len(tdh.current_card)
        pubdata["card"] = last_put_card
    dealer = tdh.room['dealer']
    if not dealer:
        dealer = ''
    pubdata["dealer"] = dealer 
    pubdata["tips"] = tips
    pubdata["all_player_data"] = all_player_data
    pubdata["game_round"] = room['game_round']
    pubdata["all_round"] = room['all_round']
    nsq_pub({'u':str(uid), 'b':bid, 't':'game', 'd':pubdata})
    if game_type == 'pdk' and stop_pop_user == str(uid):
        user_seat = members.index(str(uid))
        last_user_seat = (user_seat - 1) % len(members)
        current_user = members[last_user_seat]
        tdh.notify_next_user(current_user)
        for member in members:
            if member != str(uid):
                p = Player(member, bid, rid)
                left_num = len(p.current_card.members)
                card_warning = tdh.room['card_warning']
                if card_warning:
                    card_warning = int(card_warning)
                else:
                    card_warning = 1
                if left_num <= card_warning:
                    nsq_pub({"b":bid, "u":uid, "t":"game", "d":{"act":"card_warning", "left_num":left_num, "uid":member, "rid":tdh.rid}})
                    
def get_match_base_score(bid, mid, all_round, game_round, rid):
    db = dao.Game_DB()
    #match = db.match_info(bid, mid)
    #mround = match['mround']
    #all_round = int(all_round)
    #game_round = int(game_round)
    #win_score = mround * match['score'] + all_round - game_round
    room_info = db.get_room(rid, bid)
    win_score = room_info['base_score'] + all_round - game_round + 1
    return win_score

def json_encode(data):
    return json.dumps(data, separators=(',', ':'))

def nsq_pub(message, topic='response'):
    try:
        nsq_client = nsqd.Client("http://%s/" % config.NSQ_HTTP)
        if isinstance(message, dict):
            message = json_encode(message)
        logging.info(u"推送消息:%s" % message)
        nsq_client.pub(topic, message)
        return True
    except:
        logging.error("nsq send error", exc_info=True)
        return False
    
def push_room_cast(rid, bid, uid, data):
    rid = data['rid']
    l = List(rid)
    for member in l.members:
        nsq_pub.pub({"d":data, "u":str(member), "b":bid, "t":"game"})
    return 

def push_member_cast(members, bid, uid, data):
    for member in members:
        if not member or member == str(uid):
            continue
        nsq_pub.pub({"d":data, "u":str(member), "b":bid, "t":"game"})
    return

class Player():
    def __init__(self, uid, bid='', rid='', first=False):
        self.uid = uid
        if first:
            redisco.connection.delete("p:%s:%s:%s:current_card" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:out_card" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:dark_bar" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:white_bar" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:pair" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:eat" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s" % (bid, uid, rid))
            self.score = Hash("p:%s:%s:%s" % (bid, uid, rid))
            self.score['score'] = 0
            self.score['win_score'] = 0
            self.score['put_flag'] = ''
        else:
            self.score = Hash("p:%s:%s:%s" % (bid, uid, rid))
        self.current_card = List("p:%s:%s:%s:current_card" % (bid, uid, rid))
        self.out_card = List("p:%s:%s:%s:out_card" % (bid, uid, rid))
        self.dark_bar = List("p:%s:%s:%s:dark_bar" % (bid, uid, rid))
        self.white_bar = List("p:%s:%s:%s:white_bar" % (bid, uid, rid))
        self.pair = List("p:%s:%s:%s:pair" % (bid, uid, rid))
        self.eat = List("p:%s:%s:%s:eat" % (bid, uid, rid))

    def get_data(self):
        return {"uid":self.uid,
                "current_card":self.current_card.members,
                "out_card":self.out_card.members,
                "dark_bar":self.dark_bar.members,
                "white_bar":self.white_bar.members,
                "pair":self.pair.members,
                "eat":self.eat.members,
                "score":self.score['score'],
                }

class MaJiang():
    def __init__(self, rid, bid, dealer=None):
        self.rid = str(rid)
        if dealer:
            redisco.connection.delete("r:%s:current_card" % rid)
            redisco.connection.delete("r:%s:out_card" % rid)
            # redisco.connection.delete("r:%s" % rid)
            redisco.connection.delete("r:%s:mid" % rid)
            self.room = Hash("r:%s" % rid)
            self.room['dealer'] = dealer
            self.room['last_get_user'] = dealer
            self.room['last_put_user'] = ''
            #game_round = int(self.room.get('game_round', 0))
            #self.room['game_round'] = game_round + 1
            self.room['stop_pop_user'] = ''
            self.room['stop_pop_act'] = ''
        else:
            self.room = Hash("r:%s" % rid)
        self.current_card = List("r:%s:current_card" % rid)
        self.out_card = List("r:%s:out_card" % rid)
        self.bid = bid
        l = List("r:%s:p" % rid)
        self.members = l.members
    
    def incr_mid(self):
        return redisco.connection.incr("r:%s:mid" % self.rid)
    
    def start(self):
        self.room['status'] = 'start'
        w = [str(x) for x in range(11, 20)] * 4
        d = [str(x) for x in range(21, 30)] * 4
        t = [str(x) for x in range(31, 40)] * 4
        f = [str(x) for x in range(41, 48)] * 4
        random.shuffle(w)
        random.shuffle(d)
        random.shuffle(t)
        random.shuffle(f)
        player_cnt = len(self.members)
        init_left_card = 136 - player_cnt * 13 - 1
        #f = [str(x) for x in range(41, 48)]
        #f = f + sorted(f * 3)
        game_type = self.room['game_type']
        if game_type in ('zzmj', 'csmj'):
            #不带风的情况
            all_card = w + d + t
            init_left_card -= 28
        elif game_type == 'hzmj':
            self.room['joker'] = '10'
            f = ['10'] * 4
            all_card = w + d + t + f 
            init_left_card -= 24
        else:
            all_card = w + d + t + f
            
        random.shuffle(all_card)
        
        dealer_seat = self.members.index(self.room['dealer'])
        for i in range(player_cnt):
            idex = (dealer_seat + i) % player_cnt
            uid = self.members[idex]
            player = Player(uid, self.bid, self.rid, True)
            card = []
            for i in range(13):
                card.append(all_card.pop())
                card.sort()
            player.current_card.extend(card)
            mid = self.incr_mid()
            nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"left_card":init_left_card, "rid":self.rid, "mid":mid, "act":"game_start", "dealer":self.room['dealer'], "card":card, "game_round":self.room['game_round'], "all_round":self.room['all_round']}})
        dealer = self.room['dealer']
        self.room['last_get_user'] = dealer
        self.current_card.clear()
        self.current_card.extend(all_card)
        logging.info(u"房间rid:%s,game_round:%s,开始发牌: %s" % (self.rid, self.room['game_round'], str(self.current_card.members)))
        self.next_pop(dealer)
    

    def trans_card(self, all_card):
        res = []
        for c in all_card:
            res.append(int(c))
        res.sort()
        return res
    
    def get_horse(self, num, winner):
        seat_horse_card = [['11', '15', '19', '21', '25', '29', '31', '35', '39', '41', '45'],
                           ['12', '16', '22', '26', '32', '36', '42', '46'],
                           ['13', '17', '23', '27', '33', '37', '43', '47'],
                           ['14', '18', '24', '28', '34', '38', '44'],
                           ]
        
        horse_card = []
        dealer = self.room['dealer']
        dealer_seat = self.members.index(str(dealer))
        # 庄家座位
        winner_seat = self.members.index(str(winner))
        # 赢家的座位
        winner_seat_horse = seat_horse_card[winner_seat - dealer_seat]
        # 该赢家对应座位的马牌列表
        current_card = self.current_card.members
        jk = self.room['joker']
        if jk:
            joker_list = jk.split(",")
        else:
            joker_list = []
        all_horse_card = current_card[:num]
        for card in all_horse_card:
            if card in winner_seat_horse or card in joker_list:
                horse_card.append(card)
        logging.info(u"获取马牌:num:%s,所有马牌:%s, 已中马牌:%s,种马数量 :%s" % (num, all_horse_card, horse_card, len(horse_card)))
        return all_horse_card, horse_card
        
    def next_pop(self, uid=None, from_bar=False):
        # 发牌逻辑
        if not uid:
            last_get_user = self.room['last_get_user']
            logging.info("next_pop, last:%s" % last_get_user)
            last_player_seat = self.members.index(str(last_get_user))
            idx = (last_player_seat + 1) % len(self.members)
            uid = self.members[idx]
        
        if len(self.current_card.members) <= int(self.room['horse']):
            logging.info("over===cccccccccc========%s" % len(self.current_card.members))
            self.game_over()
            return
        card = self.current_card.pop()
        if not card:
            logging.info("over===========")
            self.game_over()
            return
        self.room['last_get_user'] = uid
        if from_bar:
            self.room['bar_get_card'] = card
        else: 
            self.room['bar_get_card'] = ''
            
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        p.current_card.append(card)
        # 判断胡牌,杠牌
        tips = []
        bar_card = []
        current_user = Hash("%s_%s" % (self.bid, uid))
        if self.room['mid'] and (current_user['online'] != 'y' or current_user['rid'] != self.rid):
            tips = []
            #离线用户不检查牌型
        else:
            if self.check_win(p, ''):
                tips.append("win")
            
            init_dark_bar = self.check_init_dark_bar(current_card)
            if self.check_bar(current_card, card):
                tips.append("dark_bar")
                bar_card.append(card)
            elif self.check_pair_bar(p.pair.members, card):
                tips.append("pair_bar")
                
            if init_dark_bar:
                tips.append("dark_bar")
                bar_card.extend(init_dark_bar)
            
        if tips:
            self.room['stop_pop_user'] = uid
            self.room['stop_pop_act'] = ",".join(tips)
        
        mid = self.incr_mid()
        left_card = len(self.current_card)
        for member in self.members:
            #if member != uid:
            #    tips = []
            data = {"b":self.bid, "u":str(member), "t":"game", "d":{"left_card":left_card, "mid":mid, "uid":uid, "act":"get_card", "card":card, "tips":tips, "bar_card":bar_card, "rid":self.rid}}
            nsq_pub(data)
        
        if not tips:
            self.notify_put(uid)
        
        if self.room['mid'] and (current_user['online'] != 'y' or current_user['rid'] != self.rid):
            self.room['stop_pop_user'] = ""
            time.sleep(0.5)
            self.put_card(uid, {"card":card})
        
    def put_card(self, uid, data):
        # 玩家出牌逻辑
        uid = str(uid)
        stop_pop_user = self.room['stop_pop_user']
        if stop_pop_user and stop_pop_user != uid:
            logging.error(u"玩家:%s有提示未处理,轮不到%s出牌" % (stop_pop_user, uid))
            return
        last_get_user = self.room['last_get_user']
        if last_get_user != uid:
            logging.error(u"该玩家:%s出牌,轮不到%s出牌" % (last_get_user, uid))
            return
        last_put_user = self.room['last_put_user']
        if uid == last_put_user:
            logging.error(u"玩家:%s不能连续出牌" % (uid))
            return
        card = data['card']
        p = Player(uid, self.bid, self.rid)
        if p.current_card.count(card) == 0:
            logging.error(u"出牌错误,该玩家没有该牌")
            return
        p.out_card.append(card)
        p.current_card.remove(card)
        #print uid, p.current_card.members
        self.room['last_put_user'] = uid
        self.room['last_get_user'] = uid
        # 检查别人是否胡牌下发提示
        stop_pop_card = False
        mid = self.incr_mid()
        tips = []
        game_type = self.room['game_type']
        tips_user = ''
        tips_user_tips = []
        for member in self.members:
            tip = []
            if game_type =='hzmj' and card == '10':
                win_card = []
                tips = []
            elif member != uid:
                win_card = []
                player = Player(member, self.bid, self.rid)
                current_card = player.current_card.members
                tips = [] 
                #比赛用户离线不做提示
                if self.room['mid']:
                    member_info = Hash("%s_%s" % (self.bid, member))
                    if member_info['online'] != 'y' or member_info['rid'] != self.rid:
                        tips = []
                    else:
                        if self.check_bar(current_card, card):
                            tips.append("bar")
                            tips.append("pair")
                        elif self.check_pair(current_card, card):
                            tips.append("pair")
                else:
                    if self.check_bar(current_card, card):
                        tips.append("bar")
                        tips.append("pair")
                    elif self.check_pair(current_card, card):
                        tips.append("pair")
                
                if tips:
                    stop_pop_card = True
                    tips_user = member
                    tips_user_tips = tips
                    self.room['stop_pop_user'] = member
                    self.room['stop_pop_act'] = ",".join(tips)
            else:
                tips = []
                win_card = self.check_win_card(p, [])
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"win_card":win_card, "mid":mid, "act":"put_card", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
            
        if tips_user:
            mid = self.incr_mid()
            nsq_pub({"b":self.bid, "u":tips_user, "t":"game", "d":{"mid":mid, "act":"tips", "card":card, "tips":tips_user_tips, "rid":self.rid, "uid":tips_user, "eat_card":[]}})
            return
        
        if not stop_pop_card:
            self.room['stop_pop_user'] = ""
            self.next_pop()

    def pass_card(self, uid, data):
        logging.info("pass:%s" % uid)
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        
        if self.room['last_get_user'] != uid:
            self.next_pop()
        else:
            self.notify_put(uid)
            
    def notify_put(self, uid):
        '''通知玩家出牌'''
        #self.room['last_get_user'] = uid
        #self.room['stop_pop_user'] = ""
        #self.room['stop_pop_act'] = ""
        return
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"turn_put", "rid":self.rid, "uid":uid}})
            
    def get_joker_cnt(self, card, joker):
        joker_cnt = 0
        for j in joker:
            k = card.count(j)
            joker_cnt += k
        return joker_cnt
    
    def get_jiang(self, card):
        r = []
        for k in set(card):
            if card.count(k) >= 2:
                r.append(k)
        return r

    def get_n(self, all_card, jiang='', joker=[]):
        n = 0
        # print "===当将牌为%s时,各种排列组合为==" % jiang
        res = []
        left_res = []
        if jiang:
            jiang = int(jiang)
        card = self.trans_card(all_card)
        card.sort()
        if jiang and card.count(jiang) >= 2:
            card.remove(jiang)
            card.remove(jiang)
            n += 1
        while card:
            c = card.pop(0)
            if card.count(c) >= 2:
                n += 1
                card.remove(c)
                card.remove(c)
                res.append([c, c, c])
            elif c > 40:
                left_res.append(c)
            else:
                c2 = c + 1
                c3 = c + 2
                if c2 in card and c3 in card:
                    card.remove(c2)
                    card.remove(c3)
                    res.append([c, c2, c3])
                    n += 1
                else:
                    left_res.append(c)

        win_card = []
        if len(left_res) == 1:
            win_card = left_res
            c1 = left_res[0]
            if c1%10 >= 4:
                if c1%10 >= 7:
                    if [c1-6, c1-5, c1-4] in res and [c1-3, c1-2, c1-1] in res:
                        win_card.extend([c1-6, c1-3, c1])
                    
                if [c1-3, c1-2, c1-1] in res:
                    win_card.extend([c1-3, c1])
                elif [c1+1, c1+1, c1+1] in res:
                    win_card.extend([c1-1, c1, c1+2])
                elif [c1+2, c1+2, c1+2] in res:
                    win_card.extend([c1, c1+1])
                elif [c1-1, c1-1, c1-1] in res:
                    win_card.extend([c1-2, c1, c1+1])
                elif [c1-2, c1-2, c1-2] in res:
                    win_card.extend([c1-1, c1])
            else:
                if [c1+1, c1+2, c1+3] in res:
                    win_card.extend([c1, c1+3])
        elif len(left_res) == 2:
            left_res.sort()
            c1 = left_res[0]
            c2 = left_res[1]
            if c2 - c1 == 0:
                win_card = [c1]
            elif c2 - c1 == 1:
                if c2 < 40:
                    if str(c2)[-1] == '9':
                        win_card = [c1-1]
                    elif str(c1)[-1] == '1':
                        win_card = [c2+1]
                    else:
                        if [c1-3, c1-2, c1-1] in res:
                            win_card = [c1-4, c1-1, c2+1]
                        else: 
                            win_card = [c1-1, c2+1]
            elif c2 - c1 == 2:
                win_card = [c1+1]
        return n, list(set(win_card))

    def check_win(self, player, card='', joker=[]):
        '''检查是否符合糊'''
        # 检查
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        #eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        #n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        
        if n == 0 and self.room['seven_pair_win'] == 'y':
            if self.check_seven_pairs(current_card, []):
                return True
            
        jiang_list = self.get_jiang(current_card)
        res = [0,]
        for jiang in jiang_list:
            allcard = self.trans_card(current_card)
            win_n, win_card = self.get_n(allcard, jiang)
            res.append(win_n)
        if max(res)+n >= 5:
            return True
        return False

    def check_win_card_old(self, player, joker=[]):
        # 检查
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        #eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        #n += len(eat)
        current_card = player.current_card.members
        jiang_list = self.get_jiang(current_card)
        res = []
        if jiang_list:
            for jiang in jiang_list:
                card = self.trans_card(current_card)
                win_n, win_card = self.get_n(card, jiang)
                if win_n == 4-n and win_card:
                    res.extend(win_card)
        card = self.trans_card(current_card)
        win_n, win_card = self.get_n(card, '')
        if win_n == 4-n and win_card:
            res.extend(win_card)
        return [str(x) for x in set(res)]

    def check_win_card(self, player, joker=[]):
        w = [str(x) for x in range(11, 20)]
        d = [str(x) for x in range(21, 30)]
        t = [str(x) for x in range(31, 40)]
        f = [str(x) for x in range(41, 48)]
        all_card = w + d + t
        if self.room['game_type'] == 'gdmj':
            all_card += f
        win_card = []
        for card in all_card:
            if self.check_win(player, card):
                win_card.append(card)
        return win_card
    
    def get_max_n(self, card_str, joker_list=[]):
        #allcard = [int(x) for x in card_str]
        #ccc = [int(x) for x in card_str]
        #joker = [int(x) for x in joker]
        allcard = []
        for x in card_str:
            allcard.append(int(x))
        ccc = []
        for x in card_str:
            ccc.append(int(x))
        joker = []
        for x in joker_list:
            joker.append(int(x))
        
        joker_cnt = self.get_joker_cnt(allcard, joker)
        if joker_cnt >= 4:
            #4张鬼牌可直接胡
            return 5
        jiang_list = self.get_jiang(allcard, joker)
        if not jiang_list:
            return 0
        #print jiang_list, '可以做将的列表'
        res = [0, ]
        for jiang in sorted(jiang_list):
            ddd = sorted(ccc)
            n, rs, left_res, win_card = self.get_n(ddd, jiang, joker)
            res.append(n)
        return max(res) + 1

    def get_win_card(self, card_str, joker_list=[], left_n=4):
        '''计算胡牌的可能性'''
        allcard = []
        for x in card_str:
            allcard.append(int(x))
        ccc = []
        for x in card_str:
            ccc.append(int(x))
        joker = []
        for x in joker_list:
            joker.append(int(x))
        jiang_list = self.get_jiang(allcard, joker)
        res = []
        if jiang_list:
            for jiang in sorted(jiang_list):
                ddd = sorted(ccc)
                n, rs, left_res, win_card = self.get_n(ddd, jiang, joker)
                n += 1
                if n == left_n:
                    res.extend(win_card)
        else:
            n, rs, left_res, win_card = self.get_n(allcard, '', joker)
            if n == left_n:
                res.extend(win_card)
        return sorted([str(x) for x in set(res)])
    
    def get_seven_pairs(self, all_card, joker=[]):
        jiang_list = []
        joker_cnt = 0
        card = self.trans_card(all_card)
        joker_list = self.trans_card(joker)
        for j in joker_list:
            m = card.count(j)
            joker_cnt += m
            for i in range(m):
                card.remove(j)
        for c in set(card):
            if card.count(c) >= 2:
                jiang_list.append(c)
                for i in range(2):
                    card.remove(c)
        if not jiang_list:
            return 0
        return len(jiang_list) + joker_cnt
    
    def check_seven_pairs(self, all_card, joker_list=[]):
        '''七对胡'''
        pair_num = self.get_seven_pairs(all_card, joker_list)
        return pair_num == 7
    
    def check_thirteen_orphans(self, all_card):
        '''十三幺'''
        jiang_list = self.get_jiang(all_card)
        if len(jiang_list) != 1:
            return False
        jiang = jiang_list[0]
        card_list = ['11', '19', '21', '29', '31', '39', '41', '42', '43', '44', '45', '46', '47']
        if set(all_card) == set(card_list) and jiang in card_list:
            return True
        return False
    
    def check_init_dark_bar(self, current_card):
        # 检查初始手牌能否暗杠
        res = []
        for k in set(current_card):
            if current_card.count(k) == 4:
                res.append(k)
        return res
    
    def check_dark_bar(self, current_card, card=''):
        # 检查摸的牌能否暗杠
        if current_card.count(card) == 4:
            return True
        return False

    def check_bar(self, current_card, card=''):
        # 检查能否杠
        if current_card.count(card) == 3:
            return True
        return False

    def check_pair_bar(self, pair, card=''):
        # 检查碰过的牌是否摸到杠
        if pair.count(card) >= 1:
            return True
        return False
    
    def check_pair(self, current_card, card=''):
        # 检查能否碰牌
        if current_card.count(card) >= 2:
            return True
        return False
    
    def dark_bar(self, uid, data):
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        card = data.get('card','')
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not card:
            for k in set(current_card):
                if current_card.count(k) == 4:
                    card = k
                    
        if not self.check_dark_bar(current_card, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            return
        p.current_card.remove(card, 4)
        p.dark_bar.append(card)
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        member_len = len(self.members)
        match_id = self.room['mid']
        if match_id:
            bar_score = 0
            every_lose_score = 0
        else:
            bar_score = (member_len - 1) * 2
            every_lose_score = 2
        mid = self.incr_mid()
        for member in self.members:
            if not match_id:
                if member == uid:
                    p.score['score'] = int(p.score['score']) + bar_score
                    logging.info(u"用户%s暗杠得%s分" % (uid, bar_score))
                else:
                    player = Player(member, self.bid, self.rid)
                    player.score['score'] = int(player.score['score']) - every_lose_score
                    logging.info(u"用户%s暗杠,%s扣%s分:%s" % (uid, member, every_lose_score, player.score['score']))
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"dark_bar", "card":card, "tips":[], "rid":self.rid, "uid":uid}})
        self.next_pop(uid)

    def pair_bar(self, uid, data):
        # 碰过别的牌, 然后自己摸到一张
        # card = data['card']
        stop_pop_user = self.room['stop_pop_user']
        if stop_pop_user and stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        p = Player(uid, self.bid, self.rid)
        card = p.current_card.members[-1]
        if not self.check_pair_bar(p.pair.members, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        p.current_card.remove(card)
        p.pair.remove(card)
        p.white_bar.append(card)
        stop_pop_card = False
        
        match_id = self.room['mid']
        if not match_id:
            member_len = len(self.members)
            bar_score = (member_len - 1)
            p.score['score'] = int(p.score['score']) + bar_score
            logging.info(u"用户%s明杠得%s分" % (uid, bar_score))
        mid = self.incr_mid()
        tips_user = ''
        tips = []
        user_seat = self.members.index(uid)
        player_cnt = len(self.members)
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = self.members[idex]
            tips = []
            if member != uid:
                player = Player(member, self.bid, self.rid)
                # 玩家有杠个扣1分
                if not match_id:
                    player.score['score'] = int(player.score['score']) - 1
                    logging.info(u"用户%s明杠,玩家%s各扣1分:%s" % (uid, member, player.score['score']))
                if tips_user:
                    pass
                else:
                    if self.room['grab_bar_win'] == 'y':
                        if self.check_win(player, card):
                            tips = ["pair_bar_win"]
                            stop_pop_card = True
                            tips_user = member
                            self.room['stop_pop_user'] = member
                            self.room['stop_pop_act'] = ",".join(tips)
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"pair_bar", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
        
        if not stop_pop_card:
            # 有抢杠胡的玩家,需要停止发牌  
            self.next_pop(uid)
        
    def bar(self, uid, data):
        # 自己有三张,直接杠别人出的牌
        # card = data['card']
        # bar_uid = data['put_card_uid']
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        
        card = last_put_player.out_card.members[-1]
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_bar(current_card, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            return
        card = last_put_player.out_card.pop()
        p.current_card.remove(card, 3)
        p.white_bar.append(card)
        
        self.room['last_get_user'] = uid
        match_id = self.room['mid'] 
        if not match_id:
            member_len = len(self.members)
            bar_score = member_len - 1
            p.score['score'] = int(p.score['score']) + bar_score
            logging.info(u"用户%s杠得3分:%s" % (uid, p.score['score']))
        mid = self.incr_mid()
        stop_pop_card = False
        tips_user = ''
        tips = []
        user_seat = self.members.index(uid)
        player_cnt = len(self.members)
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = self.members[idex]
            tips = []
            if member != uid:
                player = Player(member, self.bid, self.rid)
                # 玩家有杠个扣1分
                if not match_id:
                    player.score['score'] = int(player.score['score']) - 1
                    logging.info(u"用户%s点杠,扣3分:%s" % (member, player.score['score']))
                if tips_user:
                    pass
                else:
                    if self.room['grab_bar_win'] == 'y':
                        if self.check_win(player, card):
                            tips = ["pair_bar_win"]
                            stop_pop_card = True
                            tips_user = member
                            self.room['stop_pop_user'] = member
                            self.room['stop_pop_act'] = "bar_win"
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"bar", "card":card, "tips":tips, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user}})
            
        #for member in self.members:
        #    if member == last_put_user:
        #        if not match_id:
        ##            player = Player(member, self.bid, self.rid)
        #            player.score['score'] = int(player.score['score']) - bar_score
        #            logging.info(u"用户%s点杠,扣3分:%s" % (member, player.score['score']))
        #    nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"bar", "card":card, "tips":[], "rid":self.rid, "uid":uid, "put_card_uid":last_put_user}})
        
        if not stop_pop_card:
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            self.next_pop(uid, from_bar=True)
    
    def pair(self, uid, data):
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        # card = data['card']
        # put_card_uid = data['put_card_uid']
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_pair(current_card, card):
            logging.info(u"请求错误,该用户不能碰牌:%s" % card)
            return
        card = last_put_player.out_card.pop()
        
        p.current_card.remove(card, 2)
        p.pair.append(card)
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"pair", "card":card, "tips":[], "rid":self.rid, "uid":uid, "put_card_uid":last_put_user}})
        # p = Player(self.room['lasy_player'], self.bid, self.rid)
        # p.out_card.remove(card, -1)
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        self.notify_put(uid)
        
    def win(self, uid, data):
        if self.room['status'] != 'start':
            logging.error(u"该轮游戏已结束")
            return
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        # card = data.get('card', '')
        
        p = Player(uid, self.bid, self.rid)
        card = p.current_card.members[-1]
        # if not self.check_win(p, card):
        if not self.check_win(p, ''):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        if horse:
            horse = int(horse)
            all_horse_card, horse_card = self.get_horse(horse, uid)
            horse_num = len(horse_card)
            
        member_len = len(self.members)
        match_id = self.room['mid']
        if match_id:
            #比赛杠没有分
            all_round = int(self.room['all_round'])
            game_round = int(self.room['game_round'])
            base_score = get_match_base_score(self.bid, match_id, all_round, game_round, self.rid)
        else:
            base_score = 1
        every_lose_score = 2 * base_score * (1 + horse_num)
        win_score = every_lose_score * (member_len - 1)
        
        if self.room['bar_get_card'] == card and self.room['bar_win_duty'] == 'y':
            # 杠上开花,杠爆全包
            last_put_user = self.room['last_put_user']
            p.score['score'] = int(p.score['score']) + win_score
            last_put_player = Player(last_put_user, self.bid, self.rid)
            last_put_player.score['score'] = int(last_put_player.score['score']) - win_score
            logging.info(u"用户%s杠上开花得%s分,点杠者%s全包" % (uid, win_score, last_put_user))
        else:
            p.score['score'] = int(p.score['score']) + win_score
            logging.info(u"用户%s自摸胡牌,中%s马,得%s分" % (uid, horse_num, win_score))
            for member in self.members:
                if member != uid:
                    player = Player(member, self.bid, self.rid)
                    player.score['score'] = int(player.score['score']) - every_lose_score
                    logging.info(u"用户%s自摸胡牌,中%s马,玩家各扣%s分" % (uid, horse_num, every_lose_score))
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"win", "card":card, "tips":[], "rid":self.rid, "uid":uid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}})
        self.game_over(uid, card, all_horse_card, horse_card, horse_num, False, "win", [u"自模胡",])

    def pair_bar_win(self, uid, data):
        # 抢杠胡,杠家全包,退还之前杠的分数
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        #card = data['card']
        bar_uid = self.room['last_get_user']
        last_put_uid = self.room['last_put_user']
        bar_player = Player(bar_uid, self.bid, self.rid)
        white_bar_member = bar_player.white_bar.members
        if white_bar_member:
            card = white_bar_member[-1]
        else:
            card = data.get("card", "")
        
        p = Player(uid, self.bid, self.rid)
        if not self.check_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        bar_win_type = self.room['stop_pop_act']
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        if horse:
            horse = int(horse)
            all_horse_card, horse_card = self.get_horse(horse, uid)
            horse_num = len(horse_card)
        
        member_len = len(self.members)
        match_id = self.room['mid']
        if match_id:
            #比赛杠没有分
            bar_score = 0
            deduct_bar_score = 0
            all_round = int(self.room['all_round'])
            game_round = int(self.room['game_round'])
            base_score = get_match_base_score(self.bid, match_id, all_round, game_round, self.rid)
        else:
            if bar_win_type == "pair_bar_win":
                bar_score = 1
            else:
                bar_score = 0
            deduct_bar_score = member_len - 1
            base_score = 1
            
        every_lose_score = 2 * base_score * (1 + horse_num)
        win_score = every_lose_score * (member_len - 1)
        logging.info(u"用户%s抢杠胡,中%s马,得%s分" % (uid, horse_num, win_score))
        
        p.score['score'] = int(p.score['score']) + win_score + bar_score
        mid = self.incr_mid()
        for member in self.members:
            if member != uid:
                # 抢杠胡全包
                player = Player(member, self.bid, self.rid)
                if member == bar_uid:
                    player.pair.append(card)
                    player.white_bar.remove(card)
                    player.score['score'] = int(player.score['score']) - deduct_bar_score - win_score
                    logging.info(u"用户%s抢杠胡,中%s马,抢杠全包:%s, 扣%s分" % (uid, horse_num, bar_uid, win_score))
                else:
                    if bar_win_type == "bar_win" and member == last_put_uid:
                        player.score['score'] = int(player.score['score']) + deduct_bar_score
                    else:
                        player.score['score'] = int(player.score['score']) + bar_score
                        logging.info(u"用户%s抢杠胡,中%s马,抢杠全包,玩家退还杠扣的1分:%s" % (uid, horse_num, member))
                    
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"win", "card":card, "tips":[], "rid":self.rid, "uid":uid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}})
        self.game_over(uid, card, all_horse_card, horse_card, horse_num, False, "pair_bar_win",  [u"抢杠胡",])
        
    def game_over(self, winner='', card='', all_horse_card=[], horse_card=[], horse_num=0, from_dissmiss=False, win_type="", win_type_list=[]):
        time.sleep(1)
        if from_dissmiss:
            from_dissmiss = "y"
        else:
            from_dissmiss = "n"
        dealer = self.room['dealer']
        db = dao.Game_DB()
        player_card = []
        for uid in self.members:
            if not uid:
                continue
            p = Player(uid, self.bid, self.rid)
            p_data = p.get_data()
            
            eat_list = []
            eat_data_list = p_data['eat']
            if eat_data_list:
                for eat_data in eat_data_list:
                    eat_list.append(eat_data.split(","))
                p_data['eat'] = eat_list
            
            del p_data['out_card']
            if dealer == uid:
                is_dealer = "y"
            else:
                is_dealer = "n"
            p_data['is_dealer'] = is_dealer
            player_card.append(p_data)
            
            # 重置玩家状态,和计算分数
            if not winner:
                score = 0
                p.score['score'] = 0
                p_data['score'] = "0"
            else:
                score = int(p_data['score'])
            db.update_player(self.rid, uid, score, 0)
            player_info = db.get_player(self.rid, uid)
            p_data['user_score'] = player_info['score']
        
        
        rules = {}
        #room_info = db.get_room(self.rid, self.bid)
        #gid = room_info.get("gid")
        gid = self.room['gid']
        if gid:
            rows = db.game_rule(gid)
        else:
            rows = db.room_rule(self.rid)
            gid = ""
        for row in rows:
            k = row['param']
            v = row['value']
            rules[k] = v
        
        #比赛的牌局统一规则
        match_id = self.room['mid']
        if match_id:
            rules = {"horse":0, "grab_bar_win":"y", "grab_bar_duty":"y", "bar_win_duty":"n", "seven_pair_win":"y"}
        else:
            match_id = ""
        game_type = self.room['game_type']
        mid = self.incr_mid()
        all_room_card = self.current_card.members
        horse = self.room['horse']
        if horse:
            left_card_num = len(all_room_card) - int(horse)
            room_left_card = all_room_card[-left_card_num:]
        else:
            room_left_card = all_room_card
        for uid in self.members:
            nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"win_type_list":win_type_list, "room_left_card":room_left_card, "match_id":match_id, "gid":gid, "rules":rules, "win_type":win_type,"from_dissmiss":from_dissmiss,"dealer":self.room['dealer'], "game_round":self.room['game_round'], "player_card":player_card, "mid":mid, "act":"game_over", "winner":winner, "card":card, "rid":self.rid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}})
            try:
                if winner == uid:
                    win_round = 1
                else:
                    win_round = 0
                if db.has_user_stat(self.bid, uid, game_type):
                    db.update_user_stat(self.bid, uid, game_type, win_round)
                else:
                    db.add_user_stat(self.bid, uid, game_type, win_round, 0)
            except:
                logging.error(u"统计用户生涯错误:%s" % uid, exc_info=True)
        logging.info("game over")
        if winner:
            self.room['dealer'] = winner
        
        self.room['status'] = 'over'
        self.room['stop_pop_user'] = ''
        self.room['last_put_user'] = ''
        self.room['last_get_user'] = ''
        game_round = self.room['game_round']
        if not game_round:
            game_round = 1
        game_round = int(game_round)
        all_round = int(self.room['all_round'])
        db.game_over(self.rid, game_round)
        
        if match_id:
            nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"all_round":all_round, "match_id":match_id, "rules":rules, "win_type":win_type,"from_dissmiss":from_dissmiss,"dealer":self.room['dealer'], "game_round":self.room['game_round'], "player_card":player_card, "mid":mid, "act":"game_over", "winner":winner, "card":card, "rid":self.rid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}}, "match_club")
        self.room['game_round'] = game_round + 1
        if all_round <= game_round:
            self.dismiss(act='room_over')
        else:
            if match_id:
                exp_time = (datetime.datetime.now() + datetime.timedelta(seconds=15)).strftime("%Y-%m-%d %H:%M:%S")
                db.add_cron(self.bid, "auto_ready", self.rid, 0, exp_time)
        
    def dismiss(self, act='room_over'):
        time.sleep(1)
        db = dao.Game_DB()
        player_data = {}
        player_stat = []
        if not self.room['status']:
            logging.error(u"房间结束,未开始:%s" % self.rid)
            deduct_flag = False
            winner = ""
            for uid in self.members:
                player_stat.append({"uid":uid,"horse":0,"dark_bar":0,"white_bar":0,"score":0,"win_num":0})
        else:
            p_stat = db.player_stat(self.rid)
            #logging.info(p_stat)
            for ps in p_stat:
                ps['horse'] = int(ps['horse'])
                ps['dark_bar'] = int(ps['dark_bar'])
                ps['white_bar'] = int(ps['white_bar'])
                ps['score'] = int(ps['score'])
                ps['win_num'] = int(ps['win_num'])
                player_data[str(ps['uid'])] = ps
            deduct_flag = True
            if p_stat:
                winner = p_stat[-1]['uid']
            else:
                winner = ""
            # 排序最后一家为大赢家
            player_stat = p_stat
        
        match_id = self.room['mid']
        if not match_id:
            match_id = 0
        gid = self.room['gid']
        if not gid:
            gid = 0
        for ps in player_stat:
            if ps['uid'] == winner:
                is_winner = 'y'
            else:
                is_winner = 'n'
            db.add_room_stat(match_id, gid, self.rid, ps['uid'], ps['score'], is_winner)
            
        room_info = db.get_room(self.rid, self.bid)
        admin = room_info['admin']
        
        if not match_id:
            #比赛的房间不发送room_over
            for uid in self.members:
                nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"act":"room_over", "rid":self.rid, "player_stat":player_stat, "winner":winner, "admin":admin}})
        else:
            #比赛房间不扣房卡
            deduct_flag = False
        db.dismiss_room(self.rid)
        game_type = self.room['game_type']
        gid = self.room['gid']
        if match_id or gid:
            nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"game_type":game_type, "match_id":match_id, "gid":gid, "act":"room_over", "rid":self.rid, "player_stat":player_stat, "winner":winner, "admin":admin}}, "match_club")
            
        if deduct_flag:
            card = room_info['card']
            db.deduct_card(self.bid, admin, card)
            nsq_pub({"act":"deduct_card", "bid":self.bid, "uid":admin, "card":card, "rid":self.rid}, "total")
            logging.info(u"房间%s解散成功,扣除房卡, bid:%s,uid:%s,card:%s" % (self.rid, self.bid, admin, card))
        else:
            logging.info(u"房间%s解散成功,游戏无需扣房卡" % self.rid)
        redisco.connection.delete("r:%s:current_card" % self.rid)
        redisco.connection.delete("r:%s:out_card" % self.rid)
        redisco.connection.delete("r:%s" % self.rid)
        redisco.connection.delete("r:%s:mid" % self.rid)
        redisco.connection.delete("r:%s:p" % self.rid)


class ZZMaJiang(MaJiang):
    def start(self):
        self.room['status'] = 'start'
        w = [str(x) for x in range(11, 20)] * 4
        d = [str(x) for x in range(21, 30)] * 4
        t = [str(x) for x in range(31, 40)] * 4
        f = [str(x) for x in range(41, 48)] * 4
        random.shuffle(w)
        random.shuffle(d)
        random.shuffle(t)
        random.shuffle(f)
        player_cnt = len(self.members)
        init_left_card = 136 - player_cnt * 13 - 1
        all_card = w + d + t
        init_left_card -= 28
        random.shuffle(all_card)
        
        dealer_seat = self.members.index(self.room['dealer'])
        for i in range(player_cnt):
            idex = (dealer_seat + i) % player_cnt
            uid = self.members[idex]
            player = Player(uid, self.bid, self.rid, True)
            card = []
            for i in range(13):
                card.append(all_card.pop())
                card.sort()
            player.current_card.extend(card)
            mid = self.incr_mid()
            nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"left_card":init_left_card, "rid":self.rid, "mid":mid, "act":"game_start", "dealer":self.room['dealer'], "card":card, "game_round":self.room['game_round'], "all_round":self.room['all_round']}})
        dealer = self.room['dealer']
        self.room['last_get_user'] = dealer
        self.current_card.clear()
        self.current_card.extend(all_card)
        logging.info(u"转转麻将房间rid:%s,game_round:%s,开始发牌: %s" % (self.rid, self.room['game_round'], str(self.current_card.members)))
        self.next_pop(dealer)
        

    def next_pop(self, uid=None, from_bar=False):
        # 发牌逻辑
        if not uid:
            last_get_user = self.room['last_get_user']
            logging.info("next_pop, last:%s" % last_get_user)
            last_player_seat = self.members.index(str(last_get_user))
            idx = (last_player_seat + 1) % len(self.members)
            uid = self.members[idx]
        
        if len(self.current_card.members) <= int(self.room['horse']):
            logging.info("over===cccccccccc========%s" % len(self.current_card.members))
            self.game_over()
            return
        card = self.current_card.pop()
        if not card:
            logging.info("over===========")
            self.game_over()
            return
        self.room['last_get_user'] = uid
        if from_bar:
            self.room['bar_get_card'] = card
        else: 
            self.room['bar_get_card'] = ''
            
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        p.current_card.append(card)
        
        #检查漏胡标记, 摸牌后清除状态
        p_flag = p.score['flag']
        if p_flag == 'n':
            p.score['flag'] = ''
            
        # 判断胡牌,杠牌
        tips = []
        bar_card = []
        current_user = Hash("%s_%s" % (self.bid, uid))
        if self.room['mid'] and (current_user['online'] != 'y' or current_user['rid'] != self.rid):
            tips = []
            #离线用户不检查牌型
        else:
            if self.check_win(p, ''):
                tips.append("win")
            
            init_dark_bar = self.check_init_dark_bar(current_card)
            if self.check_bar(current_card, card):
                tips.append("dark_bar")
                bar_card.append(card)
            elif self.check_pair_bar(p.pair.members, card):
                tips.append("pair_bar")
                
            if init_dark_bar:
                tips.append("dark_bar")
                bar_card.extend(init_dark_bar)
            
        if tips:
            self.room['stop_pop_user'] = uid
            self.room['stop_pop_act'] = ",".join(tips)
        
        mid = self.incr_mid()
        left_card = len(self.current_card)
        for member in self.members:
            #if member != uid:
            #    tips = []
            data = {"b":self.bid, "u":str(member), "t":"game", "d":{"left_card":left_card, "mid":mid, "uid":uid, "act":"get_card", "card":card, "tips":tips, "bar_card":bar_card, "rid":self.rid}}
            nsq_pub(data)
        
        if not tips:
            self.notify_put(uid)
        
        if self.room['mid'] and (current_user['online'] != 'y' or current_user['rid'] != self.rid):
            self.room['stop_pop_user'] = ""
            time.sleep(0.5)
            self.put_card(uid, {"card":card})
            
    def put_card(self, uid, data, from_pass=False, repeat_user=[]):
        # 玩家出牌逻辑
        repeat = "n"
        uid = str(uid)
        #是否重复发牌给客户端
        stop_pop_user = self.room['stop_pop_user']
        if stop_pop_user and stop_pop_user != uid:
            logging.error(u"玩家:%s有提示未处理,轮不到%s出牌" % (stop_pop_user, uid))
            #views.get_last_data('', self.bid, uid, data)
            return
        last_get_user = self.room['last_get_user']
        if last_get_user != uid:
            logging.error(u"该玩家:%s出牌,轮不到%s出牌" % (last_get_user, uid))
            #views.get_last_data('', self.bid, uid, data)
            return
        last_put_user = self.room['last_put_user']
        if uid == last_put_user:
            logging.error(u"玩家:%s不能连续出牌" % (uid))
            return
        card = data['card']
        p = Player(uid, self.bid, self.rid)
        if p.current_card.count(card) == 0:
            logging.error(u"出牌错误,该玩家%s没有该牌" % uid)
            return
        p.out_card.append(card)
        p.current_card.remove(card)
        self.room['last_put_user'] = uid
        #self.room['last_get_user'] = uid
        
        #按照玩家座位顺序检查是否有胡牌可能
        members = self.members
        
        mid = self.incr_mid()
        for member in members:
            if member != uid:
                win_card = []
            else:
                win_card = self.check_win_card(p, [])
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"put_card", "repeat":"n", "mid":mid, "card":card, "tips":[], "rid":self.rid, "uid":uid, "win_card":win_card}})
        
        put_win_user = []
        user_seat = members.index(uid)
        player_cnt = len(members)
        tips = []
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = self.members[idex]
            if member != uid:
                member_info = Hash("%s_%s" % (self.bid, member))
                if self.room['mid'] and (member_info['online'] != 'y' or member_info['rid'] != self.rid):
                    tips = []
                else:
                    member_player = Player(member, self.bid, self.rid)
                    if member_player.score['flag'] != 'n':
                        if self.check_win(member_player, card):
                            put_win_user.append(member)
                    else:
                        logging.info(u"转转%s房间玩家%s漏胡,下一圈才可以检查是否胡" % (self.rid, member))
        if put_win_user:
            #点炮胡的情况
            self.room['stop_pop_user'] = ",".join(put_win_user)
            self.room['stop_pop_act'] = "put_win"
            tips = ["put_win"]
            mid = self.incr_mid()
            nsq_pub({"b":self.bid, "u":str(put_win_user[0]), "t":"game", "d":{"mid":mid, "act":"tips", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
            return
        stop_pop_card = False
        tips = []
        #game_type = self.room['game_type']
        
        mid = self.incr_mid()
        for member in members:
            if member != uid:
                win_card = []
                member_info = Hash("%s_%s" % (self.bid, member))
                if self.room['mid'] and (member_info['online'] != 'y' or member_info['rid'] != self.rid):
                    tips = []
                else:
                    player = Player(member, self.bid, self.rid)
                    current_card = player.current_card.members
                    tips = [] 
                    if self.check_bar(current_card, card):
                        tips.append("bar")
                        tips.append("pair")
                    elif self.check_pair(current_card, card):
                        tips.append("pair")
                if tips:
                    stop_pop_card = True
                    self.room['stop_pop_user'] = member
                    self.room['stop_pop_act'] = ",".join(tips)
                    nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"tips", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
                    
        if not stop_pop_card:
            self.next_pop()

    def check_pair_bar_tips(self, last_put_user='', card=''):
        if not last_put_user:
            last_put_user = self.room['last_put_user']
            last_put_player = Player(last_put_user, self.bid, self.rid)
            card = last_put_player.out_card.members[-1]
        
        members = self.members
        user_seat = members.index(last_put_user)
        next_idex = (user_seat + 1) % len(members)
        next_member = members[next_idex]
        tips_user = ''
        eat_card_list = []
        for member in members:
            if member != last_put_user:
                member_info = Hash("%s_%s" % (self.bid, member))
                if self.room['mid'] and (member_info['online'] != 'y' or member_info['rid'] != self.rid):
                    tips = []
                else:
                    player = Player(member, self.bid, self.rid)
                    current_card = player.current_card.members
                    tips = [] 
                    if self.check_bar(current_card, card):
                        tips.append("bar")
                        tips.append("pair")
                    elif self.check_pair(current_card, card):
                        tips.append("pair")
                    eat_card_list = []
                            
                if tips:
                    tips_user = member
                    self.room['stop_pop_user'] = member
                    self.room['stop_pop_act'] = ",".join(tips)
                    mid = self.incr_mid()
                    if tips_user:
                        nsq_pub({"b":self.bid, "u":tips_user, "t":"game", "d":{"mid":mid, "act":"tips", "card":card, "tips":tips, "rid":self.rid, "uid":tips_user, "eat_card":eat_card_list}})
                        return tips_user
        return False
    
    def pass_card(self, uid, data):
        logging.info("pass:%s" % uid)
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif uid not in stop_pop_user.split(","):
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        stop_pop_act = self.room['stop_pop_act']
        if "put_win" in stop_pop_act:
            player = Player(uid, self.bid, self.rid)
            player.score['flag'] = 'n'
            logging.info(u"用户胡牌点击取消执行漏胡%s" % uid)
            last_put_user = self.room['last_put_user']
            p = Player(last_put_user, self.bid, self.rid)
            #漏胡要过一圈才可以再胡
            card = p.out_card.members[-1]
            stop_pop_user_list = stop_pop_user.split(",")
            idx = stop_pop_user_list.index(uid)
            if len(stop_pop_user_list) != (idx+1):
                #给下一家可胡牌玩家推送通知
                next_player = stop_pop_user_list[idx+1]
                mid = self.incr_mid()
                tips = ["put_win"]
                nsq_pub({"b":self.bid, "u":str(next_player), "t":"game", "d":{"mid":mid, "act":"tips", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
                return
            else:
                self.room['stop_pop_user'] = ""
                self.room['stop_pop_act'] = ""
                tips_user = self.check_pair_bar_tips(last_put_user, card)
                if tips_user:
                    logging.info(u"点炮胡玩家%s:pass, 有其他玩家%s要碰牌或杠" % (uid, tips_user))
                    return
        elif "win" in stop_pop_act:
            player = Player(uid, self.bid, self.rid)
            player.score['flag'] = 'n'
            logging.info(u"用户胡牌点击取消执行漏胡%s" % uid)
            
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        
        if self.room['last_get_user'] != uid:
            self.next_pop()
        else:
            self.notify_put(uid)

    def pair_bar(self, uid, data):
        # 碰过别的牌, 然后自己摸到一张
        # card = data['card']
        stop_pop_user = self.room['stop_pop_user']
        if stop_pop_user and stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        p = Player(uid, self.bid, self.rid)
        card = p.current_card.members[-1]
        if not self.check_pair_bar(p.pair.members, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        p.current_card.remove(card)
        p.pair.remove(card)
        p.white_bar.append(card)
        stop_pop_card = False
        match_id = self.room['mid'] 
        if not match_id:
            member_len = len(self.members)
            bar_score = (member_len - 1)
            p.score['score'] = int(p.score['score']) + bar_score
            logging.info(u"用户%s明杠得%s分" % (uid, bar_score))
        mid = self.incr_mid()
        tips = []
        
        user_seat = self.members.index(uid)
        player_cnt = len(self.members)
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = self.members[idex]
            if member != uid:
                player = Player(member, self.bid, self.rid)
                if not match_id:
                    # 玩家有杠个扣1分
                    player.score['score'] = int(player.score['score']) - 1
                    logging.info(u"用户%s明杠,玩家%s各扣1分:%s" % (uid, member, player.score['score']))
                if tips:
                    pass
                else:
                    tips = []
                    if self.room['grab_bar_win'] == 'y':
                        if self.check_win(player, card):
                            tips = ["pair_bar_win"]
                            stop_pop_card = True
                            self.room['stop_pop_user'] = member
                            self.room['stop_pop_act'] = ",".join(tips)
            else:
                tips = []
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"pair_bar", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
        
        if not stop_pop_card:
            # 有抢杠胡的玩家,需要停止发牌  
            self.next_pop(uid, from_bar=True)
        
    def bar(self, uid, data):
        # 自己有三张,直接杠别人出的牌
        # card = data['card']
        # bar_uid = data['put_card_uid']
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        
        card = last_put_player.out_card.members[-1]
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_bar(current_card, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            return
        card = last_put_player.out_card.pop()
        p.current_card.remove(card, 3)
        p.white_bar.append(card)
        self.room['last_get_user'] = uid
        match_id = self.room['mid']
        if not match_id:
            #只有非比赛房间才对杠扣分
            member_len = len(self.members)
            bar_score = member_len - 1
            p.score['score'] = int(p.score['score']) + bar_score
            logging.info(u"用户%s杠得3分:%s" % (uid, p.score['score']))
        mid = self.incr_mid()
        for member in self.members:
            if member == last_put_user:
                if not match_id:
                    player = Player(member, self.bid, self.rid)
                    player.score['score'] = int(player.score['score']) - bar_score
                    logging.info(u"用户%s点杠,扣3分:%s" % (member, player.score['score']))
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"bar", "card":card, "tips":[], "rid":self.rid, "uid":uid, "put_card_uid":last_put_user}})
        
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        self.next_pop(uid, from_bar=True)

    def pair(self, uid, data):
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        # card = data['card']
        # put_card_uid = data['put_card_uid']
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_pair(current_card, card):
            logging.error(u"请求错误,该用户不能碰牌:%s" % card)
            return
        card = last_put_player.out_card.pop()
        p.score['put_flag'] = 'y'
        p.current_card.remove(card, 2)
        p.pair.append(card)
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"pair", "card":card, "tips":[], "rid":self.rid, "uid":uid, "put_card_uid":last_put_user}})
        # p = Player(self.room['lasy_player'], self.bid, self.rid)
        # p.out_card.remove(card, -1)
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        self.notify_put(uid)

    def pair_bar_win(self, uid, data):
        
        if "put_win" in self.room['stop_pop_act']:
            self.put_win(uid, data)
            return
        
        # 抢杠胡,杠家全包,退还之前杠的分数
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        #card = data['card']
        bar_uid = self.room['last_get_user']
        bar_player = Player(bar_uid, self.bid, self.rid)
        white_bar_member = bar_player.white_bar.members
        if white_bar_member:
            card = white_bar_member[-1]
        else:
            card = data.get("card", "")
        
        p = Player(uid, self.bid, self.rid)
        if not self.check_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        if horse:
            horse = int(horse)
            all_horse_card, horse_card = self.get_horse(horse, uid)
            horse_num = len(horse_card)
        
        member_len = len(self.members)
        match_id = self.room['mid']
        if match_id:
            #比赛杠没有分
            bar_score = 0
            deduct_bar_score = 0
            all_round = int(self.room['all_round'])
            game_round = int(self.room['game_round'])
            base_score = get_match_base_score(self.bid, match_id, all_round, game_round, self.rid)
        else:
            bar_score = 1
            deduct_bar_score = member_len - 1
            base_score = 1
        every_lose_score = 2 * base_score * (1 + horse_num)
        win_score = every_lose_score * (member_len - 1)
        logging.info(u"用户%s抢杠胡,中%s马,得%s分" % (uid, horse_num, win_score))
        p.score['score'] = int(p.score['score']) + win_score + bar_score
        mid = self.incr_mid()
        for member in self.members:
            if member != uid:
                player = Player(member, self.bid, self.rid)
                # 抢杠胡全包
                if member == bar_uid:
                    player.pair.append(card)
                    player.white_bar.remove(card)
                    player.score['score'] = int(player.score['score']) - deduct_bar_score - win_score
                    logging.info(u"用户%s抢杠胡,中%s马,抢杠全包:%s, 扣%s分" % (uid, horse_num, bar_uid, win_score))
                else:
                    if bar_score != 0:
                        player.score['score'] = int(player.score['score']) + bar_score
                        logging.info(u"用户%s抢杠胡,中%s马,抢杠全包,玩家退还杠扣的1分:%s" % (uid, horse_num, member))
            
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"win", "card":card, "tips":[], "rid":self.rid, "uid":uid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}})
        self.game_over(uid, card, all_horse_card, horse_card, horse_num, False, "pair_bar_win", [u"抢杠胡",])

    def put_win(self, uid, data):
        #点炮胡
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif uid not in stop_pop_user.split(","):
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        logging.info("last_put_user:%s, card:%s" % (last_put_user, card))
        p = Player(uid, self.bid, self.rid)
        if not self.check_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        
        data['card'] = card
        #for member in self.members:
        #    if member == uid:
        #        continue
        #    mid = self.incr_mid()
        #    nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"put_card", "card":card, "tips":[], "rid":self.rid, "uid":last_put_user}})
        
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        if horse:
            horse = int(horse)
            all_horse_card, horse_card = self.get_horse(horse, uid)
            horse_num = len(horse_card)
        
        member_len = len(self.members)
        match_id = self.room['mid']
        if match_id:
            #win_score = 1
            all_round = int(self.room['all_round'])
            game_round = int(self.room['game_round'])
            win_score = get_match_base_score(self.bid, match_id, all_round, game_round, self.rid)
        else:
            base_score = 1
            win_score = base_score * (1 + horse_num)
        #win_score = 2 * horse_num * (member_len - 1) + (member_len - 1)
        
        logging.info(u"房间:%s用户%s点炮胡,中%s马,得%s分" % (self.rid, uid, horse_num, win_score))
        #grab_bar_duty = self.room['grab_bar_duty']
        p.score['score'] = int(p.score['score']) + win_score
            
        mid = self.incr_mid()
        for member in self.members:
            if member != uid:
                player = Player(member, self.bid, self.rid)
                # 抢杠胡全包
                if member == last_put_user:
                    player.score['score'] = int(player.score['score']) - win_score
                    logging.info(u"房间:%s用户%s点炮胡,中%s马,点炮全包:%s, 扣%s分" % (self.rid, uid, horse_num, last_put_user, win_score))
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"win", "card":card, "tips":[], "rid":self.rid, "uid":uid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}})
        self.game_over(uid, card, all_horse_card, horse_card, horse_num, False, "put_win", [u"点炮胡",])

class HZMaJiang(MaJiang):
    '''红中麻将'''
    def start(self):
        self.room['status'] = 'start'
        self.room['joker'] = '10'
        w = [str(x) for x in range(11, 20)] * 4
        d = [str(x) for x in range(21, 30)] * 4
        t = [str(x) for x in range(31, 40)] * 4
        f = ['10', ] * 4
        random.shuffle(w)
        random.shuffle(d)
        random.shuffle(t)
        random.shuffle(f)
        player_cnt = len(self.members)
        init_left_card = 136 - player_cnt * 13 - 1
        all_card = w + d + t + f
        init_left_card -= 24
        random.shuffle(all_card)
        
        dealer_seat = self.members.index(self.room['dealer'])
        for i in range(player_cnt):
            idex = (dealer_seat + i) % player_cnt
            uid = self.members[idex]
            player = Player(uid, self.bid, self.rid, True)
            card = []
            for i in range(13):
                card.append(all_card.pop())
                card.sort()
            player.current_card.extend(card)
            mid = self.incr_mid()
            nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"left_card":init_left_card, "rid":self.rid, "mid":mid, "act":"game_start", "dealer":self.room['dealer'], "card":card, "game_round":self.room['game_round'], "all_round":self.room['all_round']}})
        dealer = self.room['dealer']
        self.room['last_get_user'] = dealer
        self.current_card.clear()
        self.current_card.extend(all_card)
        logging.info(u"红中麻将房间rid:%s,game_round:%s,开始发牌: %s" % (self.rid, self.room['game_round'], str(self.current_card.members)))
        self.next_pop(dealer)

    def trans_card(self, all_card):
        res = []
        for c in all_card:
            res.append(int(c))
        res.sort()
        return res
    
    def get_joker_cnt(self, card, joker):
        joker_cnt = 0
        for j in joker:
            k = card.count(j)
            joker_cnt += k
        return joker_cnt
    
    def get_jiang(self, card, joker=[]):
        res = []
        #card = self.trans_card(card)
        #joker = self.trans_card(joker)
        joker_cnt = 0
        for j in joker:
            k = card.count(j)
            joker_cnt += k
            #for i in range(k):
            #    card.remove(j)
        for c in set(card):
            if c in joker:
                continue
            if joker_cnt > 0 and c not in joker:
                res.append(c)
            else:
                if card.count(c) >= 2:
                    res.append(c)
        return res
    
    def get_n(self, card, jiang='', joker=[], priority='seq'):
        n = 0
        res = []
        left_res = []
        card.sort()
        joker_cnt = 0
        all_joker = []
        for j in joker:
            k = card.count(j)
            joker_cnt += k
            for i in range(k):
                all_joker.append(j)
                card.remove(j)
        if joker_cnt >= 4:
            return 4
        joker = all_joker
        if jiang:
            jiang_cnt = card.count(jiang)
            card.remove(jiang)  
            if jiang_cnt < 2:
                joker_cnt -= 1
                joker.pop()
            else:
                card.remove(jiang)
        while card:
            c = card.pop(0)
            card_num = card.count(c) 
            if card_num >= 2:
                n += 1
                card.remove(c)
                card.remove(c)
                res.append([c, c, c])
            elif card_num == 1:
                c2 = c + 1
                c3 = c + 2
                c4 = c + 3
                c2_cnt = card.count(c2)
                c3_cnt = card.count(c3)
                if c2_cnt == 2 and c3_cnt == 2 and c2/10==c/10 and c3/10==c/10:
                    n += 2
                    card.remove(c)
                    for i in range(2):
                        res.append([c, c2, c3])
                        card.remove(c2)
                        card.remove(c3)
                elif joker_cnt >= 2:
                    n += 1
                    joker_cnt -= 1
                    jk = joker.pop()
                    card.remove(c)
                    res.append([c, c, jk])
                elif c2 in card and c3 in card and c2/10==c/10 and c3/10==c/10:
                    n += 1
                    card.remove(c2)
                    card.remove(c3)
                    res.append([c, c2, c3])
                elif joker_cnt == 1:
                    if priority != 'seq':
                        n += 1
                        joker_cnt -= 1
                        jk = joker.pop()
                        card.remove(c)
                        res.append([c, c, jk])
                    elif c2 in card and c4 not in card and c2/10==c/10 and c4/10==c/10:
                        n += 1
                        card.remove(c2)
                        joker_cnt -= 1
                        jk = joker.pop()
                        res.append([c, c2, jk])
                    elif c3 in card and c4 not in card and c3/10==c/10 and c4/10==c/10:
                        n += 1
                        card.remove(c3)
                        joker_cnt -= 1
                        jk = joker.pop()
                        res.append([c, jk, c3])
                    else:
                        n += 1
                        joker_cnt -= 1
                        jk = joker.pop()
                        card.remove(c)
                        res.append([c, c, jk])
                else:
                    #break
                    left_res.append(c)
            else:
                cs1 = c - 1
                cs1_cnt = card.count(cs1)
                if cs1_cnt >= 1 and cs1/10==c/10:
                    cs1_cnt = 1
                else:
                    cs1_cnt = 0
                cs2 = c - 2
                cs2_cnt = card.count(cs2)
                if cs2_cnt >= 1 and cs2/10==c/10:
                    cs2_cnt = 1
                else:
                    cs2_cnt = 0
                    
                c2 = c + 1
                c2_cnt = card.count(c2)
                if c2_cnt >= 1 and c2/10==c/10:
                    c2_cnt = 1
                else:
                    c2_cnt = 0
                c3 = c + 2
                c3_cnt = card.count(c3)
                if c3_cnt >= 1 and c3/10==c/10:
                    c3_cnt = 1
                else:
                    c3_cnt = 0
                if c2_cnt + c3_cnt + joker_cnt >= 2:
                    n += 1
                    tmp_res = [c, ]
                    need_joker = 2 - (c2_cnt + c3_cnt)
                    joker_cnt -= need_joker
                    for i in range(c2_cnt):
                        card.remove(c2)
                        tmp_res.append(c2)
                    for i in range(c3_cnt):
                        card.remove(c3)
                        tmp_res.append(c3)
                    for i in range(need_joker):
                        jk = joker.pop()
                        tmp_res.append(jk)
                    res.append(tmp_res)
                elif cs1_cnt + c2_cnt + joker_cnt >= 2:
                    n += 1
                    tmp_res = [c, ]
                    need_joker = 2 - (cs1_cnt + c2_cnt)
                    joker_cnt -= need_joker
                    for i in range(c2_cnt):
                        card.remove(c2)
                        tmp_res.append(c2)
                    for i in range(cs1_cnt):
                        card.remove(cs1)
                        tmp_res.append(c3)
                    for i in range(need_joker):
                        jk = joker.pop()
                        tmp_res.append(jk)
                    res.append(tmp_res)
                elif cs1_cnt + cs2_cnt + joker_cnt >= 2:
                    n += 1
                    tmp_res = [c, ]
                    need_joker = 2 - (cs1_cnt + cs2_cnt)
                    joker_cnt -= need_joker
                    for i in range(cs1_cnt):
                        card.remove(cs1)
                        tmp_res.append(c2)
                    for i in range(cs2_cnt):
                        card.remove(cs2)
                        tmp_res.append(cs2)
                    for i in range(need_joker):
                        jk = joker.pop()
                        tmp_res.append(jk)
                    res.append(tmp_res)
                else:
                    # break
                    left_res.append(c)
        if joker_cnt % 3 == 0:
            n += (joker_cnt / 3)
        win_card = []
        return n, res, left_res, win_card

    def get_max_n(self, card_str, joker_list=[]):
        allcard = self.trans_card(card_str)
        ccc = self.trans_card(card_str)
        joker = self.trans_card(joker_list)
        joker_cnt = self.get_joker_cnt(allcard, joker)
        if joker_cnt >= 4:
            #4张鬼牌可直接胡
            return 5
        jiang_list = self.get_jiang(allcard, joker)
        if not jiang_list:
            return 0
        #print jiang_list, '可以做将的列表'
        res = [0, ]
        for jiang in sorted(jiang_list):
            allcard = self.trans_card(card_str)
            #logging.info(u"判断胡牌:%s,%s" % (self.rid, jiang))
            n, rs, left_res, win_card = self.get_n(allcard, jiang, joker)
            res.append(n+1)
        return max(res)

    def check_win_card(self, player, joker=[]):
        w = [str(x) for x in range(11, 20)]
        d = [str(x) for x in range(21, 30)]
        t = [str(x) for x in range(31, 40)]
        all_card = w + d + t
        win_card = []
        for card in all_card:
            if self.check_win(player, card):
                win_card.append(card)
        return win_card
    
    def check_win(self, player, card='', joker_list=[]):
        # 检查
        jk = self.room['joker']
        if jk:
            joker_list = jk.split(",")
        else:
            joker_list = []
        n = 0
        n += len(player.dark_bar)
        n += len(player.white_bar)
        n += len(player.pair)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        if n == 0 and self.room['seven_pair_win'] == 'y':
            if self.check_seven_pairs(current_card, joker_list):
                return True
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return False
        max_n = self.get_max_n(current_card, joker_list)
        logging.debug(u"用户牌型最大n:%s" % max_n)
        if n + max_n >= 5:
            return True
        return False
    
class CSMaJiang(ZZMaJiang):
    '''长沙麻将, 胡法: 点炮,自摸,海底自摸,海底点炮,杠上开花,杠上点炮,天胡,地胡(平胡)
    '''
    def is_sixi(self, all_card):
        '''四喜,小胡自摸'''
        card = self.trans_card(all_card)
        for c in set(card):
            c_cnt = card.count(c)
            if c_cnt == 4:
                return 'sixi'
        return False
    
    def is_banbanhu(self, all_card):
        '''板板胡,手牌没有258,小胡自摸'''
        card = self.trans_card(all_card)
        for c in set(card):
            if c%10 in (2, 5, 8):
                return False
        return 'banbanhu'
    
    def is_queyise(self, all_card):
        '''缺一色, 小胡自摸'''
        card = self.trans_card(all_card)
        color = {}
        for cc in set(card):
            c = str(cc/10)
            d = cc % 10
            if c in color:
                color[c]['num'] += 1
            else:
                color[c] = {"num":1, "five_num":0}
            if d == 5:
                color[c]['five_num'] += 1
                
        if len(color.keys()) <= 2:
            return 'queyise'
        for k in color.keys():
            if color[k]['num'] == 1 and color[k]['five_num'] == 1:
                return 'queyise' 
        return False
    
    def is_liuliushun(self, all_card):
        '''六六顺, 小胡自摸'''
        card = self.trans_card(all_card)
        triple_cnt = 0
        for c in set(card):
            if card.count(c) == 3:
                triple_cnt += 1
        if triple_cnt >= 2:
            return 'liuliushun'
        return False
    
    def get_jiang(self, all_card, free_jiang=True):
        res = []
        card = self.trans_card(all_card)
        for c in set(card):
            if card.count(c) >= 2:
                if free_jiang:
                    res.append(c)
                elif c%10 in (2,5,8):
                    res.append(c)
        return res
    
    def is_pinghu(self, all_card, has_n=0, win_type='put_win', free_jiang=False):
        '''平胡,258将'''
        jiang_list = self.get_jiang(all_card, free_jiang)
        res = [0,]
        for jiang in jiang_list:
            card = self.trans_card(all_card)
            n = self.get_n(card, jiang)
            res.append(n)
        if max(res)+has_n >= 5:
            if win_type == "put_win":
                return 'put_pinghu' 
            return 'pinghu'
        return False
    
    def get_n(self, all_card, jiang, joker=[]):
        n = 0
        # print "===当将牌为%s时,各种排列组合为==" % jiang
        res = []
        jiang = int(jiang)
        card = self.trans_card(all_card)
        card.sort()
        if jiang and card.count(jiang) >= 2:
            card.remove(jiang)
            card.remove(jiang)
            n += 1
        while card:
            c = card.pop(0)
            if card.count(c) >= 2:
                n += 1
                card.remove(c)
                card.remove(c)
                res.append([c, c, c])
            elif c > 40:
                break
            else:
                c2 = c + 1
                c3 = c + 2
                if c2 in card and c3 in card:
                    card.remove(c2)
                    card.remove(c3)
                    res.append([c, c2, c3])
                    n += 1
                else:
                    break
        return n

    def is_qixiaodui(self, all_card):
        '''七小对'''
        pair = 0
        bomb = 0
        card = self.trans_card(all_card)
        for c in set(card):
            if card.count(c) == 4:
                bomb += 1
                pair += 2
            elif card.count(c) == 2:
                pair += 1
        if pair == 7:
            if bomb >= 2:
                '''双豪华七小对'''
                return 'two_qixiaodui'
            elif bomb == 1:
                '''豪华七小对'''
                return 'one_qixiaodui' 
            return 'qixiaodui'
        return False
    
    def is_pengpenghu(self, all_card, has_n=0):
        '''碰碰胡,AAABBBCCCDDD乱将'''
        res = [0]
        jiang_list = self.get_jiang(all_card)
        for jiang in jiang_list:
            card = self.trans_card(all_card)
            card.remove(jiang)
            card.remove(jiang)
            triple = 0
            for c in set(card):
                if card.count(c) == 3:
                    triple += 1
            res.append(triple+1)
        if max(res)+has_n >= 5:
            return 'pengpenghu'
        return False
    
    def is_jiangjianghu(self, all_card):
        '''将将胡,每张牌都是258'''
        card = self.trans_card(all_card)
        for c in set(card):
            if c%10 not in (2,5,8):
                return False
        return 'jiangjianghu'
    
    def is_qingyise(self, all_card):
        '''清一色'''
        card = self.trans_card(all_card)
        color = card[0]/10
        for c in set(card):
            if c/10 != color:
                return False
        return 'qingyise'
    
    def is_dandiao(self, all_card, jiang, has_n):
        '''全求人'''
        if len(all_card) != 2:
            return False
        n = self.get_n(all_card, jiang)
        if n+has_n >= 5:
            return 'dandiao'
        return False
    
    def check_win(self, player, card='', joker=[]):
        '''检查是否符合自模糊'''
        # 检查
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        
        #tianhu = False
        #dihu = False
        #out_card = self.out_card.members
        #if not out_card:
        #    tianhu = True
        #elif len(out_card) == 1:
        #    dihu = True
        logging.info(u"长沙判断用户%s是否胡牌:%s" % (player.uid, str(current_card)))
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return []
        if self.is_qixiaodui(current_card):
            return True
        elif self.is_pengpenghu(current_card, len(pair)+len(dark_bar)+len(white_bar)):
            return True
        put_flag = player.score['put_flag']
        if not put_flag:
            #只能是起手的牌符合要求才行
            sixi = self.is_sixi(current_card[:-1])
            if sixi:
                return sixi
            liuliushun = self.is_liuliushun(current_card[:-1])
            if liuliushun:
                return liuliushun
            banbanhu = self.is_banbanhu(current_card)
            if banbanhu:
                return banbanhu
            queyise = self.is_queyise(current_card)
            if queyise:
                return queyise
        all_card = []
        all_card.extend(current_card)
        if dark_bar:
            all_card.extend(dark_bar)
        if white_bar:
            all_card.extend(white_bar)
        if pair:
            all_card.extend(pair)
        if eat:
            for eat_card in eat:
                all_card.extend(eat_card.split(","))
        if self.is_jiangjianghu(all_card):
            return True
            
        qingyise = self.is_qingyise(all_card)
        if qingyise or len(current_card) <= 2: 
            free_jiang = True
        else:
            free_jiang = False
        if self.is_pinghu(current_card, n, "win", free_jiang):
            return True
        return False
    
    def get_win_score(self, win_type_list):
        score = 0
        win_type_score = {"sixi":2,"banbanhu":2,"queyise":2,"liuliushun":2,"put_pinghu":1,"pinghu":2, "pengpenghu":6,"jiangjianghu":6,"qingyise":6,"haidi_win":6,
                 "haidi_put_win":6,"qixiaodui":6,"one_qixiaodui":12,"two_qixiaodui":18,"bar_win":6,"pair_bar_win":6,"bar_put_win":6,
                 "dandiao":6, "tianhu":6, "dihu":6, "quanqiuren":6,
                 }
        for win_type in win_type_list:
            score += win_type_score[win_type]
        return score
    
    def trans_win_type(self, win_type_list):
        res = []
        win_type_name = {"sixi":{"score":2, "name":u"四喜"}, "banbanhu":{"score":2, "name":u"板板胡"},"queyise":{"score":2, "name":u"缺一色"},
                         "liuliushun":{"score":2, "name":u"六六顺"},"put_pinghu":{"score":1, "name":u"平胡"}, "pinghu":{"score":2, "name":u"平胡"}, "pengpenghu":{"score":6, "name":u"碰碰胡"},
                         "jiangjianghu":{"score":6, "name":u"将将胡"},"qingyise":{"score":6, "name":u"清一色"},"haidi_win":{"score":6, "name":u"海底捞月"},
                         "haidi_put_win":{"score":6, "name":u"海底炮"},"qixiaodui":{"score":6, "name":u"七小对"},"one_qixiaodui":{"score":12, "name":u"豪华七小对"},
                         "two_qixiaodui":{"score":18, "name":u"双豪华七小对"},"bar_win":{"score":6, "name":u"杠上开花"},"pair_bar_win":{"score":6, "name":u"抢杠胡"},
                         "bar_put_win":{"score":6, "name":u"杠上炮"},"dandiao":{"score":6, "name":u"全求人"}, "tianhu":{"score":6, "name":u"天胡"}, "dihu":{"score":6, "name":u"地胡",},
                         }
        for win_type in win_type_list:
            msg = u"%s %s分" % (win_type_name[win_type]['name'], win_type_name[win_type]['score'])
            res.append(msg)
        return res
    
    def get_win_type(self, player, card=''):
        '''获取用户符合自模糊的哪种类型'''
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return []
        res = []
        qixiaodui = self.is_qixiaodui(current_card)
        if qixiaodui:
            res.append(qixiaodui)
        
        pinghu = self.is_pinghu(current_card, n, 'win')
        if pinghu:
            res.append(pinghu)
        put_flag = player.score['put_flag']
        if not put_flag:
            liuliushun = self.is_liuliushun(current_card)
            if liuliushun:
                res.append(liuliushun)
            #这几种牌型只能自摸
            sixi = self.is_sixi(current_card)
            if sixi:
                res.append(sixi)
                
        pengpenghu = self.is_pengpenghu(current_card, len(pair)+len(dark_bar)+len(white_bar))
        if pengpenghu:
            res.append(pengpenghu)
        
        dandiao = self.is_dandiao(current_card, current_card[-1], n)
        if dandiao:
            res.append(dandiao)
        all_card = []
        all_card.extend(current_card)
        if dark_bar:
            all_card.extend(dark_bar)
        if white_bar:
            all_card.extend(white_bar)
        if pair:
            all_card.extend(pair)
        if eat:
            for eat_card in eat:
                all_card.extend(eat_card.split(","))
        jiangjianghu = self.is_jiangjianghu(all_card)
        if jiangjianghu:
            res.append(jiangjianghu)
        
        if not put_flag:
            banbanhu = self.is_banbanhu(all_card)
            if banbanhu:
                res.append(banbanhu)
            quyise = self.is_queyise(all_card)
            if quyise:
                res.append(quyise)
        qingyise = self.is_qingyise(all_card)
        if qingyise:
            res.append(qingyise)
        
        if len(res) > 1:
            if "pinghu" in res:
                res.remove("pinghu")
        return res
    
    def get_eat_card(self, all_card, card):
        '''获取可吃的牌'''
        card = int(card)
        if card > 40:
            return []
        c = card % 10
        n = card / 10
        res = []
        point_res = []
        if c == 9:
            point_res = [[7, 8]]
        elif c == 8:
            point_res = [[6, 7], [7, 9]]
        elif c == 7:
            point_res = [[5, 6], [6, 8], [8, 9]]
        elif c == 6:
            point_res = [[4, 5], [5, 7], [7, 8]]
        elif c == 5:
            point_res = [[3, 4], [4, 6], [6, 7]]
        elif c == 4:
            point_res = [[2, 3], [3, 5], [5, 6]]
        elif c == 3:
            point_res = [[1, 2], [2, 4], [4, 5]]
        elif c == 2:
            point_res = [[1, 3], [3, 4]]
        elif c == 1:
            point_res = [[2, 3]]
        for [s, e] in point_res:
            c1 = str(n*10+s)
            c2 = str(n*10+e)
            if c1 in all_card and c2 in all_card:
                res.append([c1, c2])
        return res
    
    def check_eat(self, all_card, card):
        '''判断能否吃card牌'''
        card = int(card)
        all_card = [int(x) for x in all_card]
        all_card.append(card)
        all_card.sort()
        if len(all_card) == 3 and (all_card[0]+1) == all_card[1] and (all_card[0]+2) == all_card[2]:
            return True
        return False
    
    def check_put_win(self, player, card='', joker=[]):
        '''点炮胡检查'''
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return False
        if self.is_qixiaodui(current_card):
            return True
        elif self.is_pengpenghu(current_card, len(pair)+len(dark_bar)+len(white_bar)):
            return True
        all_card = []
        all_card.extend(current_card)
        if dark_bar:
            all_card.extend(dark_bar)
        if white_bar:
            all_card.extend(white_bar)
        if pair:
            all_card.extend(pair)
        if eat:
            for eat_card in eat:
                all_card.extend(eat_card.split(","))
        jiangjianghu = self.is_jiangjianghu(all_card)
        if jiangjianghu:
            return True
        if self.is_qingyise(all_card) or len(current_card) <= 2:
            free_jiang = True
        else:
            free_jiang = False
        if self.is_pinghu(current_card, n, "put_win", free_jiang):
            return True
        return False
    
    def get_put_win_type(self, player, card='', joker=[]):
        '''点炮胡可胡的类型'''
        n = 0
        res = []
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return []
        qixiaodui = self.is_qixiaodui(current_card)
        if qixiaodui:
            res.append(qixiaodui)
        else:
            pinghu = self.is_pinghu(current_card, n, "put_win")
            if pinghu:
                res.append(pinghu)
            pengpenghu = self.is_pengpenghu(current_card, len(pair)+len(dark_bar)+len(white_bar))
            if pengpenghu:
                res.append(pengpenghu)
            dandiao = self.is_dandiao(current_card, card, n)
            if dandiao:
                res.append(dandiao)
        all_card = []
        all_card.extend(current_card)
        if dark_bar:
            all_card.extend(dark_bar)
        if white_bar:
            all_card.extend(white_bar)
        if pair:
            all_card.extend(pair)
        if eat:
            for eat_card in eat:
                all_card.extend(eat_card.split(","))
        jiangjianghu = self.is_jiangjianghu(all_card)
        if jiangjianghu:
            res.append(jiangjianghu)
        qingyise = self.is_qingyise(all_card)
        if qingyise:
            res.append(qingyise)
        
        if len(res) > 1:
            if "put_pinghu" in res:
                res.remove("put_pinghu")
        return res
    

    def next_pop(self, uid=None, from_bar=False):
        # 发牌逻辑
        if not uid:
            last_get_user = self.room['last_get_user']
            logging.info("next_pop, last:%s" % last_get_user)
            last_player_seat = self.members.index(str(last_get_user))
            idx = (last_player_seat + 1) % len(self.members)
            uid = self.members[idx]
        
        if len(self.current_card.members) <= int(self.room['horse']):
            logging.info("over===cccccccccc========%s" % len(self.current_card.members))
            self.game_over()
            return
        card = self.current_card.pop()
        if not card:
            logging.info("over===========")
            self.game_over()
            return
        self.room['last_get_user'] = uid
        if from_bar:
            self.room['bar_get_card'] = card
        else: 
            self.room['bar_get_card'] = ''
            
        p = Player(uid, self.bid, self.rid)
        #检查漏胡标记, 摸牌后清除状态
        p_flag = p.score['flag']
        if p_flag == 'n':
            p.score['flag'] = ''
        tips = []
        bar_card = []
        current_user = Hash("%s_%s" % (self.bid, uid))
        win_type = ""
        if self.room['mid'] and (current_user['online'] != 'y' or current_user['rid'] != self.rid):
            tips = []
            #离线用户不检查牌型
        else:
            win_type = self.check_win(p, card)
            if win_type:
                tips.append("win")
            
            current_card = p.current_card.members
            init_dark_bar = self.check_init_dark_bar(current_card)
            if self.check_bar(current_card, card):
                tips.append("dark_bar")
                bar_card.append(card)
            elif self.check_pair_bar(p.pair.members, card):
                tips.append("pair_bar")
                
            if init_dark_bar:
                tips.append("dark_bar")
                bar_card.extend(init_dark_bar)
            
        if tips:
            self.room['stop_pop_user'] = uid
            self.room['stop_pop_act'] = ",".join(tips)
        p.current_card.append(card)
        mid = self.incr_mid()
        left_card = len(self.current_card)
        for member in self.members:
            #if member != uid:
            #    tips = []
            data = {"b":self.bid, "u":str(member), "t":"game", "d":{"left_card":left_card, "mid":mid, "uid":uid, "act":"get_card", "card":card, "tips":tips, "bar_card":bar_card, "rid":self.rid}}
            nsq_pub(data)
        
        if not self.out_card and win_type in ("sixi", "banbanhu", "liuliushun", "queyise"):
            self.win(uid, {"card":card})
            return
        
        if not tips:
            self.notify_put(uid)
        
        if self.room['mid'] and (current_user['online'] != 'y' or current_user['rid'] != self.rid):
            self.room['stop_pop_user'] = ""
            time.sleep(0.5)
            self.put_card(uid, {"card":card})
            
    def put_card(self, uid, data, from_pass=False, repeat_user=[]):
        # 玩家出牌逻辑
        repeat = "n"
        uid = str(uid)
        #是否重复发牌给客户端
        stop_pop_user = self.room['stop_pop_user']
        if stop_pop_user and stop_pop_user != str(uid):
            logging.error(u"玩家:%s有提示未处理,轮不到%s出牌" % (stop_pop_user, uid))
            return
        last_put_user = self.room['last_put_user']
        if uid == last_put_user:
            logging.error(u"玩家:%s不能连续出牌" % (uid))
            return
        card = data['card']
        p = Player(uid, self.bid, self.rid)
        if p.current_card.count(card) == 0:
            logging.error(u"出牌错误,该玩家没有该牌")
            return
        p.out_card.append(card)
        p.current_card.remove(card)
        self.room['last_put_user'] = uid
        self.room['last_get_user'] = uid
        p.score['put_flag'] = 'y'
        members = self.members
        player_cnt = len(members)
        mid = self.incr_mid()
        put_win_user = []
        #按照玩家座位顺序检查是否有胡牌可能
        match_id = self.room['mid']
        user_seat = members.index(uid)
        tips = []
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = members[idex]
            if member != uid:
                member_info = Hash("%s_%s" % (self.bid, member))
                if match_id and (member_info['online'] != 'y' or member_info['rid'] != self.rid):
                    tips = []
                else:
                    member_player = Player(member, self.bid, self.rid)
                    tips = []
                    if p.score['flag'] != 'n': 
                        if self.check_put_win(member_player, card):
                            put_win_user.append(member)
                win_card = []
            else:
                win_card = []
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"win_card":win_card, "repeat":repeat, "mid":mid, "act":"put_card", "card":card, "tips":[], "rid":self.rid, "uid":uid}})
            
        if len(put_win_user) >= 1:
            #点炮胡的情况
            self.room['stop_pop_user'] = ",".join(put_win_user)
            self.room['stop_pop_act'] = "put_win"
            tips = ["put_win",]
            mid = self.incr_mid()
            nsq_pub({"b":self.bid, "u":str(put_win_user[0]), "t":"game", "d":{"mid":mid, "act":"tips", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
            return
        
        res = self.check_pair_bar_tips(uid, card)
        if res:
            logging.info(u"有玩家%s要碰牌或杠:%s" % (res, card))
            return
        res = self.check_eat_tips(uid, card)
        if res:
            logging.info(u"有玩家%s要吃牌:%s" % (res, card))
            return
        
        #所有提示都没有的情况,继续下家发牌
        self.next_pop()
            
    def check_pair_bar_tips(self, last_put_user='', card=''):
        if not last_put_user:
            last_put_user = self.room['last_put_user']
            last_put_player = Player(last_put_user, self.bid, self.rid)
            card = last_put_player.out_card.members[-1]
        
        members = self.members
        user_seat = members.index(last_put_user)
        next_idex = (user_seat + 1) % len(members)
        next_member = members[next_idex]
        tips_user = ''
        eat_card_list = []
        for member in members:
            if member != last_put_user:
                member_info = Hash("%s_%s" % (self.bid, member))
                if self.room['mid'] and (member_info['online'] != 'y' or member_info['rid'] != self.rid):
                    tips = []
                else:
                    player = Player(member, self.bid, self.rid)
                    current_card = player.current_card.members
                    tips = [] 
                    if self.check_bar(current_card, card):
                        tips.append("bar")
                        tips.append("pair")
                    elif self.check_pair(current_card, card):
                        tips.append("pair")
                        
                    if tips and member == next_member:
                        eat_card_list = self.get_eat_card(current_card, card)
                        if eat_card_list:
                            tips.append("eat")
                    else:
                        eat_card_list = []
                            
                if tips:
                    tips_user = member
                    self.room['stop_pop_user'] = member
                    self.room['stop_pop_act'] = ",".join(tips)
                    mid = self.incr_mid()
                    if tips_user:
                        nsq_pub({"b":self.bid, "u":tips_user, "t":"game", "d":{"mid":mid, "act":"tips", "card":card, "tips":tips, "rid":self.rid, "uid":tips_user, "eat_card":eat_card_list}})
                        return tips_user
        return False
    
    def check_eat_tips(self, last_put_user='', card=''):
        if not last_put_user:
            last_put_user = self.room['last_put_user']
            last_put_player = Player(last_put_user, self.bid, self.rid)
            card = last_put_player.out_card.members[-1]
        
        members = self.members
        user_seat = members.index(last_put_user)
        next_idex = (user_seat + 1) % len(members)
        next_member = members[next_idex]
        next_player = Player(next_member, self.bid, self.rid)
        next_player_card = next_player.current_card.members
        tips = []
        eat_card_list = self.get_eat_card(next_player_card, card)
        if eat_card_list:
            tips = ['eat',]
            self.room['stop_pop_user'] = next_member
            self.room['stop_pop_act'] = ",".join(tips)
            mid = self.incr_mid()
            nsq_pub({"b":self.bid, "u":next_member, "t":"game", "d":{"act":"tips", "mid":mid, "card":card, "tips":tips, "rid":self.rid, "uid":next_member, "eat_card":eat_card_list}})
            return next_member
        return False
    
    def pass_card(self, uid, data):
        logging.info("pass:%s" % uid)
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif uid not in stop_pop_user.split(","):
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        last_put_user = self.room['last_put_user']
        stop_pop_act = self.room['stop_pop_act']
        p = Player(last_put_user, self.bid, self.rid)
        card = p.out_card.members[-1]
        if "put_win" in stop_pop_act:
            p.score['flag'] = 'n'
            stop_pop_user_list = stop_pop_user.split(",")
            idx = stop_pop_user_list.index(uid)
            if len(stop_pop_user_list) != (idx+1):
                #给下一家可胡牌玩家推送通知
                next_player = stop_pop_user_list[idx+1]
                mid = self.incr_mid()
                tips = ["put_win",]
                nsq_pub({"b":self.bid, "u":str(next_player), "t":"game", "d":{"mid":mid, "act":"tips", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
                return
            else:
                #所有可点炮胡的玩家都通知完
                self.room['stop_pop_user'] = ""
                self.room['stop_pop_act'] = ""
                tips_user = self.check_pair_bar_tips(last_put_user, card)
                if tips_user:
                    logging.info(u"点炮胡玩家%s:pass, 有其他玩家%s要碰牌或杠" % (uid, tips_user))
                    return
                tips_user = self.check_eat_tips(last_put_user, card)
                if tips_user:
                    logging.info(u"点炮胡玩家%s:pass, 有其他玩家:%s要吃牌" % (uid, tips_user))
                    return
        elif "pair" in stop_pop_act or "bar" in stop_pop_act:
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            if "eat" not in stop_pop_act:
                tips_user = self.check_eat_tips(last_put_user, card)
                if tips_user:
                    logging.info(u"碰,杠玩家%s:pass, 有其他玩家:%s要吃牌" % (uid, tips_user))
                    return
        
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        
        if self.room['last_get_user'] != uid:
            self.next_pop()
        else:
            self.notify_put(uid)
    

    def pair_bar(self, uid, data):
        # 碰过别的牌, 然后自己摸到一张，杠没有分
        # card = data['card']
        stop_pop_user = self.room['stop_pop_user']
        if stop_pop_user and stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        p = Player(uid, self.bid, self.rid)
        card = p.current_card.members[-1]
        if not self.check_pair_bar(p.pair.members, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        p.current_card.remove(card)
        p.pair.remove(card)
        p.white_bar.append(card)
        stop_pop_card = False
        mid = self.incr_mid()
        tips = []
        user_seat = self.members.index(uid)
        player_cnt = len(self.members)
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = self.members[idex]
            if member != uid:
                player = Player(member, self.bid, self.rid)
                if tips:
                    pass
                else:
                    tips = []
                    if self.room['grab_bar_win'] == 'y':
                        if self.check_win(player, card):
                            tips = ["pair_bar_win"]
                            stop_pop_card = True
                            self.room['stop_pop_user'] = member
                            self.room['stop_pop_act'] = ",".join(tips)
            else:
                tips = []
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"pair_bar", "card":card, "tips":tips, "rid":self.rid, "uid":uid}})
        
        if not stop_pop_card:
            # 有抢杠胡的玩家,需要停止发牌  
            self.next_pop(uid, from_bar=True)
        
    def bar(self, uid, data):
        # 自己有三张,直接杠别人出的牌
        # card = data['card']
        # bar_uid = data['put_card_uid']
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        
        card = last_put_player.out_card.members[-1]
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_bar(current_card, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            return
        p.score['put_flag'] = 'y'
        card = last_put_player.out_card.pop()
        p.current_card.remove(card, 3)
        p.white_bar.append(card)
        mid = self.incr_mid()
        self.room['last_get_user'] = uid
        tips = []
        stop_pop_card = False
        user_seat = self.members.index(uid)
        player_cnt = len(self.members)
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = self.members[idex]
            if member != uid:
                player = Player(member, self.bid, self.rid)
                if tips:
                    pass
                else:
                    tips = []
                    if self.room['grab_bar_win'] == 'y':
                        if self.check_win(player, card):
                            tips = ["pair_bar_win"]
                            stop_pop_card = True
                            self.room['stop_pop_user'] = member
                            self.room['stop_pop_act'] = "bar_win"
            else:
                tips = []
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"bar", "card":card, "tips":tips, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user}})
        
        if not stop_pop_card:
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            self.next_pop(uid, from_bar=True)
        
    def eat(self, uid, data):
        '''吃牌'''
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        # card = data['card']
        # put_card_uid = data['put_card_uid']
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        eat_card_list = self.get_eat_card(current_card, card)
        if not eat_card_list:
            logging.error(u"请求错误,该用户不能吃这张牌:%s" % card)
            return
        
        eat_card = data['eat_card']
        c1 = eat_card[0]
        c2 = eat_card[1]
        if c1 not in current_card or c2 not in current_card or not self.check_eat(eat_card, card):
            logging.error(u"吃牌错误,该用户%s不能吃这张牌:%s" % (uid, card))
            return
        card = last_put_player.out_card.pop()
        p.current_card.remove(eat_card[0], 1)
        p.current_card.remove(eat_card[1], 1)
        p.score['put_flag'] = 'y'
        eat_card_list = [c1, c2, card]
        eat_card_list.sort()
        p.eat.append(",".join(eat_card_list))
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"eat", "card":card, "eat_card":eat_card_list, "tips":[], "rid":self.rid, "uid":uid, "put_card_uid":last_put_user}})
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        self.notify_put(uid)
        
    def win(self, uid, data):
        if self.room['status'] != 'start':
            logging.error(u"该轮游戏已结束")
            return
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        # card = data.get('card', '')
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        card = current_card[-1]
        # if not self.check_win(p, card):
        if not self.check_win(p, ''):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        if horse:
            horse = int(horse)
            all_horse_card, horse_card = self.get_horse(horse, uid)
            horse_num = len(horse_card)
        else:
            horse = 0
        member_len = len(self.members)
        win_type_list = self.get_win_type(p, '')
        
        dealer = self.room['dealer']
        #dealer_player = Player(dealer, self.bid, self.rid)
        #out_card = dealer_player.out_card.members
        if str(uid) == dealer and "sixi" not in win_type_list and "liuliushun" not in win_type_list and "banbanhu" not in win_type_list and "queyise" not in win_type_list:
            win_type_list.append("tianhu")
        else:
            if self.room['bar_get_card'] == card:
                #杠上开花
                win_type_list.append("bar_win")
            room_left_card = self.current_card.members
            if not room_left_card or len(room_left_card) == horse:
                #海底捞月
                win_type_list.append("haidi_win")
        score = self.get_win_score(win_type_list)
        win_type_list = self.trans_win_type(win_type_list)
        logging.info(u"自模糊:%s" % str(win_type_list))
        #base_score = 1
        if score > 12:
            score = 12
        every_lose_score = score + horse_num * 2
        win_score = every_lose_score * (member_len - 1)
        
        p.score['score'] = int(p.score['score']) + win_score
        
        logging.info(u"用户%s自摸胡牌,中%s马,得%s分" % (uid, horse_num, win_score))
        for member in self.members:
            if member != uid:
                player = Player(member, self.bid, self.rid)
                player.score['score'] = int(player.score['score']) - every_lose_score
                logging.info(u"用户%s自摸胡牌,中%s马,玩家各扣%s分" % (uid, horse_num, every_lose_score))
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"win", "card":card, "tips":[], "rid":self.rid, "uid":uid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}})
        self.game_over(uid, card, all_horse_card, horse_card, horse_num, win_type="win", win_type_list=win_type_list)
        
    def put_win(self, uid, data):
        #点炮胡
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif uid not in stop_pop_user.split(","):
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        logging.info("last_put_user:%s, card:%s" % (last_put_user, card))
        p = Player(uid, self.bid, self.rid)
        if not self.check_put_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        if horse:
            horse = int(horse)
            all_horse_card, horse_card = self.get_horse(horse, uid)
            horse_num = len(horse_card)
        else:
            horse = 0
        current_card = p.current_card.members
        data['card'] = card
        win_type_list = self.get_put_win_type(p, card)
        logging.info(u"点炮胡:%s" % str(win_type_list))
        if self.room['bar_get_card'] == card:
            #杠上开花
            win_type_list.append("bar_put_win")
        room_left_card = self.current_card.members
        if not room_left_card or len(room_left_card) == horse:
            #海底捞月
            win_type_list.append("haidi_put_win")
        members = self.members
        for member in members:
            if member != str(uid):
                player = Player(member, self.bid, self.rid)
                current_card = player.current_card.members
                if self.check_bar(current_card, card):
                    win_type_list.append("pair_bar_win")
        
        base_score = 1
        score = self.get_win_score(win_type_list)
        if score > 12:
            score = 12
        win_score = score + horse_num * 2
        logging.info(u"房间:%s用户%s点炮胡,中%s马,得%s分" % (self.rid, uid, horse_num, win_score))
        win_type_list = self.trans_win_type(win_type_list)
        logging.info(u"点炮胡:%s" % str(win_type_list))
        #grab_bar_duty = self.room['grab_bar_duty']
        p.score['score'] = int(p.score['score']) + win_score
        mid = self.incr_mid()
        for member in members:
            if member != uid:
                player = Player(member, self.bid, self.rid)
                # 抢杠胡全包
                if member == last_put_user:
                    player.score['score'] = int(player.score['score']) - win_score
                    logging.info(u"房间:%s用户%s点炮胡,中%s马,点炮全包:%s, 扣%s分" % (self.rid, uid, horse_num, last_put_user, win_score))
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"win", "card":card, "tips":[], "rid":self.rid, "uid":uid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}})
        self.game_over(uid, card, all_horse_card, horse_card, horse_num, win_type="put_win", win_type_list=win_type_list)
        
    def pair_bar_win(self, uid, data):
        # 抢杠胡,杠家全包,退还之前杠的分数
        stop_pop_user = self.room['stop_pop_user']
        if not stop_pop_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            return
        elif stop_pop_user != uid:
            logging.error(u"玩家%s有提示, 不该%s操作" % (stop_pop_user, uid))
            return
        #card = data['card']
        bar_uid = self.room['last_get_user']
        bar_player = Player(bar_uid, self.bid, self.rid)
        white_bar_member = bar_player.white_bar.members
        if white_bar_member:
            card = white_bar_member[-1]
        else:
            card = data.get("card", "")
        p = Player(uid, self.bid, self.rid)
        if not self.check_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        if horse:
            horse = int(horse)
            all_horse_card, horse_card = self.get_horse(horse, uid)
            horse_num = len(horse_card)
        else:
            horse = 0
        win_type_list = self.get_win_type(p, card)
        room_left_card = self.current_card.members
        if not room_left_card or len(room_left_card) == horse:
            #海底捞月
            win_type_list.append("haidi_win")
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        score = self.get_win_score(win_type_list)
        member_len = len(self.members)
        if score > 12:
            score = 12
        every_lose_score = score + horse_num * 2
        win_score = every_lose_score * (member_len - 1)
        win_type_list = self.trans_win_type(win_type_list)
        logging.info(u"用户%s抢杠胡,中%s马,得%s分" % (uid, horse_num, win_score))
        p.score['score'] = int(p.score['score']) + win_score
        mid = self.incr_mid()
        for member in self.members:
            if member != uid:
                player = Player(member, self.bid, self.rid)
                # 抢杠胡全包
                if member == bar_uid:
                    player.pair.append(card)
                    player.white_bar.remove(card)
                    player.score['score'] = int(player.score['score']) - win_score
                    logging.info(u"用户%s抢杠胡,中%s马,抢杠全包:%s, 扣%s分" % (uid, horse_num, bar_uid, win_score))
            
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"mid":mid, "act":"win", "card":card, "tips":[], "rid":self.rid, "uid":uid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}})
        self.game_over(uid, card, all_horse_card, horse_card, horse_num, win_type="pair_bar_win", win_type_list=win_type_list)
        
class PaoDeKuai():
    '''跑得快'''
    def __init__(self, rid, bid, dealer=None):
        self.rid = str(rid)
        if dealer:
            redisco.connection.delete("r:%s:current_card" % rid)
            redisco.connection.delete("r:%s:mid" % rid)
            self.room = Hash("r:%s" % rid)
            self.room['dealer'] = dealer
            self.room['last_get_user'] = dealer
            self.room['last_put_user'] = ''
            self.room['stop_pop_user'] = ''
            self.room['stop_pop_act'] = ''
        else:
            self.room = Hash("r:%s" % rid)
        self.current_card = List("r:%s:current_card" % rid)
        self.bid = bid
        l = List("r:%s:p" % rid)
        self.members = l.members
    
    def incr_mid(self):
        return redisco.connection.incr("r:%s:mid" % self.rid)
    
    def get_card_point(self, c):
        '''获取某张扑克牌的点数'''
        return int(c)/10
    
    def trans_card(self, card):
        '''转换手牌列表,去掉花色'''
        res = []
        card.sort()
        for c in card:
            card_point = self.get_card_point(c)
            res.append(card_point)
        return res
    
    def is_pair(self, card_list):
        '''是否对子'''
        if len(card_list) == 2:
            if card_list[0] == card_list[1]:
                return True, [card_list[0]]
        return False, []
    
    def is_seq_pair(self, card_list):
        '''连对'''
        res = []
        card_list.sort()
        if len(card_list) >= 4 and len(card_list) % 2 == 0:
            for c in set(card_list):
                if card_list.count(c) != 2:
                    return False, []
                res.append(c)
            res.sort()
            start_i = res[0]
            end_i = res[-1]
            if res == range(start_i, end_i+1):
                return True, [start_i, end_i]
        return False, []
    
    def is_bomb(self, card_list):
        '''炸弹'''
        if len(card_list) == 4:
            if card_list[0] == card_list[1] and card_list[0] == card_list[2] and card_list[0] == card_list[3]:
                return True, [card_list[0]]
        return False, []
    
    def is_bomb_one(self, card_list):
        '''炸弹带1'''
        bomb_list = []
        single_list = []
        if len(card_list) == 5:
            for c in set(card_list):
                c_cnt = card_list.count(c)
                if c_cnt == 4:
                    bomb_list.append(c)
                else:
                    single_list.extend([c]*c_cnt)
            if len(bomb_list) == 1 and len(single_list) == 1:
                return True, bomb_list
        return False, []
    
    def is_bomb_two(self, card_list):
        '''炸弹带2'''
        bomb_list = []
        single_list = []
        if len(card_list) == 6:
            for c in set(card_list):
                c_cnt = card_list.count(c)
                if c_cnt == 4:
                    bomb_list.append(c)
                else:
                    single_list.extend([c]*c_cnt)
            if len(bomb_list) == 1 and len(single_list) == 2:
                return True, bomb_list
        return False, []
    
    def is_bomb_three(self, card_list):
        '''炸弹带3'''
        bomb_list = []
        single_list = []
        if len(card_list) == 7:
            for c in set(card_list):
                c_cnt = card_list.count(c)
                if c_cnt == 4:
                    bomb_list.append(c)
                else:
                    single_list.extend([c]*c_cnt)
            if len(bomb_list) == 1 and len(single_list) == 3:
                return True, bomb_list
        return False, []
    
    def is_triple_without(self, card_list):
        '''三不带'''
        if len(card_list) == 3:
            if card_list[0] == card_list[1] and card_list[0] == card_list[2]:
                return True, [card_list[0]]
        return False, []
    
    def is_triple_one(self, card_list):
        '''三带一'''
        triple_list = []
        single_list = []
        if len(card_list) == 4:
            for c in set(card_list):
                c_cnt = card_list.count(c)
                if c_cnt == 3:
                    triple_list.append(c)
                else:
                    single_list.extend([c]*c_cnt)
            if len(triple_list) == 1 and len(single_list) == 1:
                return True, triple_list
        return False, []
    
    def is_triple_two(self, card_list):
        '''三带二'''
        triple_list = []
        single_list = []
        if len(card_list) == 5:
            for c in set(card_list):
                c_cnt = card_list.count(c)
                if c_cnt == 3:
                    triple_list.append(c)
                else:
                    single_list.extend([c]*c_cnt)
            if len(triple_list) == 1 and len(single_list) == 2:
                return True, triple_list
        return False, []
    
    def is_seq(self, card_list):
        '''顺子'''
        card_list.sort()
        start_i = card_list[0]
        end_i = card_list[-1]
        if card_list == range(start_i, end_i+1):
            return True, [start_i, end_i]
        return False, []
    
    def is_seq_triple(self, card_list):
        '''飞机'''
        single_list = []
        triple_list = []
        card_list.sort()
        if len(card_list) >= 6:
            for c in set(card_list):
                c_cnt = card_list.count(c)
                if c_cnt >= 3:
                    triple_list.append(c)
                else:
                    single_list.extend([c]*c_cnt)
            if len(triple_list) >= 2:
                triple_list.sort()
                start_i = triple_list[0]
                end_i = triple_list[-1]
                if triple_list == range(start_i, end_i+1) and (len(card_list)- len(triple_list) * 3) <= len(triple_list) * 2:
                    return True, [start_i, end_i]
                else:
                    seq_list = []
                    for i in range(1, len(triple_list)):
                        for j in range(len(triple_list)):
                            tmp_seq = range(triple_list[j], triple_list[j]+i)
                            if all(map(lambda x: x in triple_list, tmp_seq)):
                                seq_list.append(tmp_seq)
                    res = []
                    for seq in seq_list:
                        if len(seq) > len(res):
                            res = seq
                    if res and (len(card_list)-len(res)*3) <= len(res)*2:
                        return True, [res[0], res[-1]]
        return False, []
    
    def get_card_type(self, card):
        card_list = self.trans_card(card)
        card_len = len(card_list)
        if card_len >= 5:
            #检查是否顺子
            #检查是否三带二
            #检查是否连对
            #检查是否飞机
            #四带3
            #四带2
            #四带1
            res = self.is_seq(card_list)
            if res[0]:
                return 'seq', res[1]
            res = self.is_seq_pair(card_list)
            if res[0]:
                return 'seq_pair', res[1]
            res = self.is_triple_two(card_list)
            if res[0]:
                return 'triple_two', res[1]
            res = self.is_seq_triple(card_list)
            if res[0]:
                return 'seq_triple', res[1]
            res = self.is_bomb_three(card_list)
            if res[0]:
                return 'bomb_three', res[1]
            res = self.is_bomb_two(card_list)
            if res[0]:
                return 'bomb_two', res[1]
            res = self.is_bomb_one(card_list)
            if res[0]:
                return 'bomb_one', res[1]
            
        elif card_len == 4:
            #检查连对
            #检查炸弹
            #检查三带一
            res = self.is_bomb(card_list)
            if res[0]:
                return 'bomb', res[1]
            res = self.is_seq_pair(card_list)
            if res[0]:
                return 'seq_pair', res[1]
            res = self.is_triple_one(card_list)
            if res[0]:
                return 'triple_one', res[1]
        elif card_len == 3:
            #三不带
            res = self.is_triple_without(card_list)
            if res[0]:
                return 'triple', res[1]
        elif card_len == 2:
            res = self.is_pair(card_list)
            if res[0]:
                return 'pair', res[1]
        elif card_len == 1:
            return 'single', card_list
        return '', []
    
    def compare_card(self, card1, card2):
        #判断card2是否比card1牌型大
        card_type2 = self.get_card_type(card2)
        card_type1 = self.get_card_type(card1)
        if card_type1[0] == card_type2[0]:
            #相同类型的牌
            if len(card1) != len(card2):
                return False
            card1_point_s = card_type1[1][0]
            card1_point_e = card_type1[1][-1]
            card2_point_s = card_type2[1][0]
            card2_point_e = card_type2[1][-1]
            if card2_point_s > card1_point_s and card2_point_e > card1_point_e:
                return True
        elif card_type2[0] == 'bomb':
            return True
        return False
    
    def get_card_by_point(self, card, card_point, num=4):
        '''取手牌中某个点数的固定数量的牌'''
        res = []
        for c in card:
            if self.get_card_point(c) == card_point and len(res) < num:
                res.append(c)
        return res
    
    def get_bomb_card(self, card, bomb_point=0):
        '''取手牌中大于bomb_point的炸弹, 为0则返回所有炸弹'''
        res = []
        tips_list = []
        card_list = self.trans_card(card)
        bomb_list = []
        for c in set(card_list):
            if card_list.count(c) == 4 and c > bomb_point:
                bomb_list.append(c)
        for bomb in bomb_list:
            tips_card = []
            for i in range(1, 5):
                tips_card.append(str(bomb * 10 + i))
            res.extend(tips_card)
            tips_list.append(tips_card)
        return res, tips_list

    def get_single_card(self, card, single_point=0):
        '''取手牌中大于single_point点数的单张牌'''
        res = []
        tips_list = []
        card_list = self.trans_card(card)
        for c in set(card_list):
            if c > single_point:
                rs = self.get_card_by_point(card, c)
                res.extend(rs)
                tips_card = rs[:1]
                tips_list.append(tips_card)
        return res, tips_list
    
    def get_pair_card(self, card, pair_point=0):
        '''取手牌中大于pair_point点数的对子扑克牌'''
        res = []
        tips_list = []
        pair_list = []
        card_list = self.trans_card(card)
        for c in set(card_list):
            if card_list.count(c) >= 2:
                if c > pair_point:
                    pair_list.append(c)
        for card_point in pair_list:
            rs = self.get_card_by_point(card, card_point)
            res.extend(rs)
            tips_card = rs[:2]
            tips_list.append(tips_card)
        return res, tips_list
    
    def get_seq_card(self, card, seq_s=0, num=5):
        '''获取手牌中包含大于某个点数的顺子对应的扑克牌'''
        seq_list = []
        end_c = 13 - num
        for start_c in range(seq_s+1, end_c+1):
            rs = range(start_c, start_c+num)
            seq_list.append(rs)
        card_list = self.trans_card(card)
        res = []
        tips_list = []
        has_seq_set = set()
        for seq in seq_list:
            if set(seq).issubset(set(card_list)):
                has_seq_set |= set(seq)
                tips_card = []
                for c in seq:
                    rs = self.get_card_by_point(card, c, 1)
                    tips_card.append(rs[0])
                tips_list.append(tips_card)
        has_seq_list = list(has_seq_set)
        for card_point in has_seq_list:
            rs = self.get_card_by_point(card, card_point)
            res.extend(rs)
        return res, tips_list
    
    def get_seq_pair_card(self, card, seq_s=0, num=2):
        '''取手牌中包含大于seq_s的连对'''
        seq_pair_list = []
        end_c = 13 - num
        for start_c in range(seq_s+1, end_c+1):
            rs = range(start_c, start_c+num)
            seq_pair_list.append(rs)
        card_list = self.trans_card(card)
        pair_list = []
        for c in set(card_list):
            if card_list.count(c) >= 2:
                pair_list.append(c)
        res = []
        tips_list = []
        has_seq_set = set()
        for seq in seq_pair_list:
            if set(seq).issubset(set(pair_list)):
                has_seq_set |= set(seq)
                tips_card = []
                for c in seq:
                    rs = self.get_card_by_point(card, c, 2)
                    tips_card.extend(rs)
                tips_list.append(tips_card)
        has_seq_list = list(has_seq_set)
        for card_point in has_seq_list:
            rs = self.get_card_by_point(card, card_point)
            res.extend(rs)
        return res, tips_list
    
    def get_triple_card(self, card, triple_point=0):
        '''取手牌中包含大于triple_point的3张'''
        if len(card) < 5:
            return [], []
        res = []
        tips_list = []
        triple_list = []
        card_list = self.trans_card(card)
        for c in set(card_list):
            if card_list.count(c) >= 3:
                if c > triple_point:
                    triple_list.append(c)
        for card_point in triple_list:
            rs = self.get_card_by_point(card, card_point)
            res.extend(rs)
            tips_card = rs[:3]
            with_card_list = []
            other_list = list(set(card_list) - set([card_point]))
            for c in other_list:
                rs = self.get_card_by_point(card, c, 3)
                with_card_list.extend(rs)
                    
            with_card = with_card_list[:2]
            tips_card.extend(with_card)
            tips_list.append(tips_card)
        if res:
            return card, tips_list
        return res, tips_list
    
    def get_bomb_three_card(self, card, bomb_point=0):
        '''取手牌中包含大于bomb'''
        if len(card) < 6:
            return [], []
        res = []
        tips_list = []
        bomb_list = []
        card_list = self.trans_card(card)
        for c in set(card_list):
            if card_list.count(c) >= 4:
                if c > bomb_point:
                    bomb_list.append(c)
        for card_point in bomb_list:
            rs = self.get_card_by_point(card, card_point)
            res.extend(rs)
            tips_card = rs[:4]
            with_card_list = []
            other_list = list(set(card_list) - set([card_point]))
            for c in other_list:
                rs = self.get_card_by_point(card, c, 3)
                with_card_list.extend(rs)
                    
            with_card = with_card_list[:3]
            tips_card.extend(with_card)
            tips_list.append(tips_card)
        if res:
            return card, tips_list
        return res, tips_list
    
    def get_seq_triple_card(self, card, seq_s=0, num=2):
        '''取手牌中包含大于seq_s的飞机'''
        if len(card) < 3 * num + 2*num:
            return [], []
        seq_triple_list = []
        end_c = 13 - num
        for start_c in range(seq_s+1, end_c+1):
            rs = range(start_c, start_c+num)
            seq_triple_list.append(rs)
        card_list = self.trans_card(card)
        triple_list = []
        for c in set(card_list):
            c_cnt = card_list.count(c)
            if c_cnt >= 3:
                triple_list.append(c)
        res = []
        tips_list = []
        has_seq_set = set()
        for seq in seq_triple_list:
            if set(seq).issubset(set(triple_list)):
                has_seq_set |= set(seq)
                with_card_list = []
                other_list = list(set(card_list) - set(seq))
                for c in other_list:
                    rs = self.get_card_by_point(card, c, 3)
                    with_card_list.extend(rs)
                tips_card = []
                with_card = []
                for c in seq:
                    rs = self.get_card_by_point(card, c, 3)
                    tips_card.extend(rs)
                    for i in range(2):
                        w = with_card_list.pop()
                        with_card.append(w)
                tips_card.extend(with_card)
                tips_list.append(tips_card)
        has_seq_list = list(has_seq_set)
        for card_point in has_seq_list:
            rs = self.get_card_by_point(card, card_point)
            res.extend(rs)
        if res:
            return card, tips_list
        return res, tips_list
    
    def check_validate(self, card, card_type):
        return self.get_card_type(card)[0] == card_type

    def get_valid_card(self, current_card, last_put_card, last_put_type='', last_put_point=''):
        valid_card = []
        if not last_put_type:
            last_put_type, last_put_point = self.get_card_type(last_put_card)
        if last_put_type == 'single':
            valid_card = self.get_single_card(current_card, int(last_put_point[0]))
        elif last_put_type == 'pair':
            valid_card = self.get_pair_card(current_card, int(last_put_point[0]))
        elif last_put_type == 'seq_pair':
            valid_card = self.get_seq_pair_card(current_card, int(last_put_point[0]), int(last_put_point[1])-int(last_put_point[0])+1)
        elif last_put_type == 'seq':
            valid_card = self.get_seq_card(current_card, int(last_put_point[0]), len(last_put_card))
        elif last_put_type == 'triple_two':
            valid_card = self.get_triple_card(current_card, int(last_put_point[0]))
        elif last_put_type == 'seq_triple':
            valid_card = self.get_seq_triple_card(current_card, int(last_put_point[0]), int(last_put_point[1])-int(last_put_point[0])+1)
        elif last_put_type == 'bomb_three':
            valid_card = self.get_bomb_three_card(current_card, int(last_put_point[0]))
        if last_put_type == 'bomb':
            valid_card = self.get_bomb_card(current_card, int(last_put_point[0]))
        else:
            bomb_card = self.get_bomb_card(current_card, 0)
            valid_list = bomb_card[0]
            tips_list = bomb_card[1]
            if valid_card:
                valid_card[0].extend(valid_list)
                valid_card[1].extend(tips_list)
            else:
                valid_card = bomb_card
        return valid_card
    
    def start(self):
        self.room['status'] = 'start'
        game_round = int(self.room['game_round'])
        all_card = []
        for i in range(10, 140, 10):
            for j in range(1, 5):
                all_card.append(i+j)
        #去掉3个2一个A
        for c in (124, 132, 133, 134):
            all_card.remove(c)
        dealer = self.room['dealer']
        random.shuffle(all_card)
        random.shuffle(all_card)
        members = self.members
        all_card_num = len(all_card)
        player_cnt = len(members)
        black_three = 11
        #第一局黑桃3先出
        
        player_card = []
        every_player_num = all_card_num/player_cnt
        for uid in members:
            player_card.append({"uid":uid, "left_num":every_player_num})
        
        first_card = []
        user_card = {}
        for uid in members:
            card = []
            for i in range(every_player_num):
                card.append(all_card.pop())
            card.sort()
            card.reverse()
            if black_three in card and game_round == 1:
                dealer = uid
                self.room['dealer'] = dealer
                black_three_first = self.room['black_three_first']
                if black_three_first == 'y':
                    first_card = ['11',]
                else:
                    black_three_first = 'n'
            user_card[uid] = card
            
        for uid in members:
            mid = self.incr_mid()
            player = Player(uid, self.bid, self.rid, True)
            card = user_card[uid]
            player.current_card.extend(card)
            card_list = [str(x) for x in card]
            nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"act":"game_start", "left_card":0, "rid":self.rid, "mid":mid, "dealer":dealer, "card":card_list, "game_round":self.room['game_round'], "all_round":self.room['all_round'], "player_card":player_card}})
            
        
        self.room['last_put_user'] = ''
        self.room['last_put_card'] = ''
        self.room['last_put_type'] = ''
        self.room['last_put_point'] = ''
        self.room['stop_pop_user'] = dealer
        self.current_card.clear()
        logging.info(u"跑得快房间rid:%s,game_round:%s,发牌结束,通知%s出牌" % (self.rid, self.room['game_round'], dealer))
        self.notify_keep_put(dealer)
    
    def notify_keep_put(self, uid):
        last_put_user = self.room['last_put_user']
        self.room['stop_pop_user'] = uid
        self.room['last_get_user'] = uid
        self.room['last_put_user'] = ''
        self.room['last_put_card'] = ''
        self.room['last_put_type'] = ''
        self.room['last_put_point'] = ''
        #mid = self.incr_mid()
        members = self.members
        player_cnt = len(members)
        max_single = 'n'
        #下家报单可以不出最大的牌
        match_id = self.room['mid']
        if not match_id:
            user_seat = members.index(uid)
            next_seat = (user_seat+1) % player_cnt
            next_user = members[next_seat]
            next_player = Player(next_user, self.bid, self.rid)
            if len(next_player.current_card.members) == 1:
                max_single = 'y'
                
        for member in members:
            if member == uid:
                tips_list = []
                player = Player(uid, self.bid, self.rid)
                all_card = player.current_card.members
                #current_card = sorted(all_card, key=lambda x:int(x))
                #for c in current_card:
                #    tips_list.append([c])
                card_type, card_point = self.get_card_type(all_card)
                if card_type and card_type not in ('bomb_one', 'bomb_two', 'bomb_three'):
                    tips_list.append(all_card)
            else:
                all_card = []
                tips_list = []
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"act":"turn_put", "put_type":"free", "max_single":max_single, "uid":uid, "valid_list":all_card, "rid":self.rid, "tips_list":tips_list, "last_put_card":[], "last_put_type":"", "last_put_point":[]}})
        
        if match_id:
            current_user = Hash("%s_%s" % (self.bid, uid))
            if current_user['online'] != 'y' or current_user['rid'] != self.rid:
                self.auto_put(uid)
            
    def notify_next_user(self, pre_user):
        members = self.members
        pre_user_seat = members.index(pre_user)
        next_user_seat = (pre_user_seat + 1) % len(members)
        next_user = members[next_user_seat]
        self.room['stop_pop_user'] = next_user
        last_put_user = self.room['last_put_user']
        if not last_put_user or next_user == last_put_user:
            #首次出牌或者过一圈没人能打起
            self.notify_keep_put(next_user)
            return
        else:
            max_single = 'n'
            last_put_card = self.room['last_put_card'].split(",")
            last_put_type = self.room['last_put_type']
            last_put_point = self.room['last_put_point'].split(",")
            if last_put_point:
                last_put_point = [int(x) for x in last_put_point]
            #判断下家能否打牌,没有打牌则自动发送要不起,否则发送出牌通知
            #last_put_type, last_put_point = self.get_card_type(last_put_card)
            p = Player(next_user, self.bid, self.rid)
            current_card = p.current_card.members
            logging.info(u"判断下家是否有牌:%s, last_put_card:%s, type:%s, point:%s" % (next_user, str(last_put_card), last_put_type, str(last_put_point)))
            valid_card = self.get_valid_card(current_card, last_put_card, last_put_type, last_put_point)
            #mid = self.incr_mid()
            match_id = self.room['mid']
            if last_put_type == 'single' and valid_card:
                
                next_next_user_seat = (next_user_seat+1) % len(members)
                next_next_user = members[next_next_user_seat]
                next_next_player = Player(next_next_user, self.bid, self.rid)
                logging.info(u"上家出的单牌, 检查下家%s是否报单, %s" % (next_next_user, str(next_next_player.current_card.members)))
                if len(next_next_player.current_card.members) == 1:
                    max_single = 'y'
                    logging.info(u"下家%s报单" % next_next_user)
                    
            for member in members:
                if member == next_user:
                    valid_list, tips_list = valid_card
                    logging.info(u"下家%s可出的牌有:valid_list:%s, tips_list:%s" % (member, str(valid_list), str(tips_list)))
                    if max_single == 'y':
                        valid_list = sorted(valid_list, key=lambda x:int(x))[-1:]
                        tips_list = sorted(tips_list, key=lambda x:sum([int(y) for y in x]))[-1:]
                    #logging.info(u"下家%s可出的牌有:%s" % (member, str(tips_list)))
                else: 
                    #logging.info(u"=============member:%s,next_user:%s" % (member, next_user))
                    valid_list, tips_list = [], []
                nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"act":"turn_put", "put_type":"follow", "max_single":max_single, "uid":next_user, "rid":self.rid, "valid_list":valid_list, "tips_list":tips_list, "last_put_card":last_put_card, "last_put_type":last_put_type, "last_put_point":last_put_point}})
            
            if match_id:
                current_user = Hash("%s_%s" % (self.bid, next_user))
                if current_user['online'] != 'y' or current_user['rid'] != self.rid:
                    self.auto_put(next_user)
    
    def pass_card(self, uid, data={}):
        stop_pop_user = self.room['stop_pop_user']
        if uid != stop_pop_user:
            logging.error(u"pass,该%s打牌,不该%s" % (stop_pop_user, uid))
            get_last_data('', self.bid, uid, {"rid":self.rid})
            return
        members = self.members
        for member in members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"pass", "uid":uid, "rid":self.rid}})
        self.notify_next_user(uid)
        
    def put_card(self, uid, data):
        uid = str(uid)
        stop_pop_user = self.room['stop_pop_user']
        if uid != stop_pop_user:
            logging.error(u"该%s出牌,不该%s" % (stop_pop_user, uid))
            get_last_data('', self.bid, uid, {"rid":self.rid})
            return
        card = data['card']
        if not isinstance(card, list):
            card = card.split(",")
        put_card_type = self.get_card_type(card)
        logging.info(u"跑得快检查用户牌型%s,%s" % (put_card_type[0], put_card_type[1]))
        card_type = put_card_type[0]
        if not card_type:
            #牌型不符合
            logging.error(u"%s出牌不符合规范,%s" % (uid, ",".join(card)))
            get_last_data('', self.bid, uid, {"rid":self.rid})
            return 
        
        current_player = Player(uid, self.bid, self.rid)
        user_current_card = current_player.current_card.members
        
        if len(user_current_card) == 16:
            black_three_first = self.room['black_three_first']
            game_round = int(self.room['game_round'])
            dealer = self.room['dealer']
            if black_three_first == 'y' and game_round == 1 and str(uid) == dealer:
                black_three = '11'
                if black_three not in card:
                    logging.error(u"首局%s出牌必须包含黑桃3,%s" % (uid, self.rid))
                    return
                    
        for c in card:
            if c not in user_current_card:
                logging.error(u"出牌异常,用户%s没有该手牌,%s" % (uid, c))
                get_last_data('', self.bid, uid, {"rid":self.rid})
                return
            elif card.count(c) > 1:
                logging.error(u"出牌异常,用户%s该牌重复%s" % (uid, c))
                return
        if card_type in ('triple', 'triple_one', 'bomb_two', 'bomb_one'):
            if len(user_current_card) != len(card):
                logging.error(u"出牌异常,用户%s只有最后一手才能出三带一和不带%s" % (uid, str(card)))
                get_last_data('', self.bid, uid, {"rid":self.rid})
                return
        elif card_type == 'seq_triple':
            seq_s, seq_e = put_card_type[1]
            if len(user_current_card) != len(card) and len(card) != (seq_e - seq_s + 1)*5:
                logging.error(u"出牌异常,用户%s只有最后一手才能飞机少带%s" % (uid, str(card)))
                get_last_data('', self.bid, uid, {"rid":self.rid})
                return
            
        last_put_type = self.room['last_put_type']
        last_put_user = self.room['last_put_user']
        last_put_point = self.room['last_put_point']
        logging.info(u"last_put_point===:%s" % str(last_put_point))
        last_put_card = self.room['last_put_card']
        members = self.members
        match_id = self.room['mid']
        if last_put_card:
            #跟上家的牌
            put_type = 'follow'
            card1 = last_put_card.split(",")
            if not self.compare_card(card1, card):
                logging.error(u"出牌异常,用户%s出牌牌不能大过上家,%s" % (uid, ",".join(card)))
                get_last_data('', self.bid, uid, {"rid":self.rid})
                return
        else:
            #自由出牌
            put_type = 'free'
        
        if not match_id:
            user_seat = members.index(uid)
            next_seat = (user_seat+1) % len(members)
            next_user = members[next_seat]
            next_player = Player(next_user, self.bid, self.rid)
            next_player_card = next_player.current_card.members
            if len(next_player_card) == 1 and card_type == 'single':
                valid_card = self.get_single_card(current_player.current_card.members, int(put_card_type[1][0]))
                
                if valid_card[0]:
                    logging.error(u"出牌异常,用户%s出牌%s,必须出最大的牌, %s" % (uid, ",".join(card), ",".join(current_player.current_card.members)))
                    return
        
        for c in card:
            current_player.current_card.remove(c, 1)
            current_player.out_card.append(c)
            #self.current_card.append(c)
        
        
        
                    
        self.room['last_put_card'] = ",".join(card)
        self.room['last_put_type'] = card_type
        self.room['last_put_point'] = ",".join([str(x) for x in put_card_type[1]])
        self.room['last_put_user'] = uid
        
        user_left_card = current_player.current_card.members
        left_num = len(user_left_card)
        win_score = 0
        
        if match_id:
            #比赛杠没有分
            all_round = int(self.room['all_round'])
            game_round = int(self.room['game_round'])
            base_score = get_match_base_score(self.bid, match_id, all_round, game_round, self.rid)
        else:
            base_score = 1
        
        if last_put_type == 'bomb':
            for member in members:
                player = Player(member, self.bid, self.rid)
                if member == last_put_user:
                    current_player.dark_bar.remove(last_put_card.split(",")[0])
                    player.score['score'] = int(player.score['score']) - 20*base_score
                else:
                    player.score['score'] = int(player.score['score']) + 10*base_score
                    
        for member in members:
            if card_type == 'bomb':
                if member == str(uid):
                    win_score = 20 * base_score
                    current_player.score['score'] =  int(current_player.score['score']) + win_score
                    current_player.dark_bar.append(card[0])
                else:
                    win_score = -10 * base_score
                    player = Player(member, self.bid, self.rid)
                    player.score['score'] = int(player.score['score']) + win_score
                    
            if member == str(uid):
                left_card = user_left_card
            else:
                left_card = []
                
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"put_card", "put_type":put_type, "left_card":left_card, "left_num":left_num, "uid":uid, "rid":self.rid, "card":card, "card_type":card_type}})
        
        if user_left_card:
            card_warning = self.room['card_warning']
            if not card_warning:
                card_warning = 1
            else:
                card_warning = int(card_warning)
            if left_num <= card_warning:
                for member in members:
                    nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"card_warning", "left_num":left_num, "uid":uid, "rid":self.rid}})
            self.notify_next_user(uid)
        else:
            duty_uid = ''
            if card_type == 'single' and put_type == 'follow':
                #报单没有出最大的单牌导致放走后包赔
                card1 = last_put_card.split(",")
                #last_put_seat = members.index(last_put_user)
                my_seat = members.index(uid)
                #if (my_seat - last_put_seat)%len(members) == 1:
                if members[my_seat - 1] == last_put_user:
                    last_put_player = Player(last_put_user, self.bid, self.rid)
                    all_card = last_put_player.current_card.members
                    logging.info(u"%s报单出完了检查用户%s是否该包赔:%s,%s" % (uid, last_put_user, str(all_card), str(last_put_point)))
                    #valid_card = self.get_single_card(all_card, int(last_put_point))
                    valid_bomb_card = self.get_bomb_card(all_card)
                    #if valid_card[0] or valid_bomb_card[0]:
                    if valid_bomb_card[0]:
                        duty_uid = last_put_user
                        logging.info(u"跑得快%s玩家%s没有出最大的牌,包赔" % (self.rid, last_put_user))
            self.game_over(uid, False, duty_uid)
    
    def auto_put(self, uid):
        uid = str(uid)
        stop_pop_user = self.room['stop_pop_user']
        if uid != stop_pop_user:
            logging.error(u"该%s出牌,不该%s" % (stop_pop_user, uid))
            return
        last_put_user = self.room['last_put_user']
        p = Player(uid, self.bid, self.rid)
        if not last_put_user or uid == last_put_user:
            #首次出牌或者过一圈没人能打起
            current_card = sorted(p.current_card.members, key=lambda x:int(x))
            card = current_card[0]
            data = {"card":[card]}
            self.put_card(uid, data)
            return
        else:
            last_put_card = self.room['last_put_card'].split(",")
            last_put_type = self.room['last_put_type']
            last_put_point = self.room['last_put_point'].split(",")
            current_card = p.current_card.members
            valid_list, tips_list = self.get_valid_card(current_card, last_put_card, last_put_type, last_put_point)
            if tips_list:
                card = tips_list[0]
                data = {"card":card}
                self.put_card(uid, data)
            else:
                self.pass_card(uid)
                
    def game_over(self, winner='', from_dissmiss=False, duty_uid=''):
        time.sleep(1)
        if from_dissmiss:
            from_dissmiss = "y"
        else:
            from_dissmiss = "n"
        dealer = self.room['dealer']
        db = dao.Game_DB()
        player_card = []

        match_id = self.room['mid']
        if match_id:
            #比赛杠没有分
            all_round = int(self.room['all_round'])
            game_round = int(self.room['game_round'])
            base_score = get_match_base_score(self.bid, match_id, all_round, game_round, self.rid)
        else:
            base_score = 1
            
        win_score = 0
        if winner:
            for uid in self.members:
                if uid != winner:
                    p = Player(uid, self.bid, self.rid)
                    left_card_num = p.current_card.members
                    if len(left_card_num) > 1:
                        lose_score = len(left_card_num) * base_score
                        if len(left_card_num) == 16:
                            lose_score *= 2
                        win_score += lose_score
                        if duty_uid:
                            duty_player = Player(duty_uid, self.bid, self.rid)
                            duty_player.score['score'] = int(duty_player.score['score']) - lose_score
                            duty_player.score['win_score'] = "-%s" % lose_score
                            logging.info(u"跑得快%s玩家%s没有出最大的牌,包赔====" % (self.rid, duty_uid))
                        else:
                            p.score['score'] = int(p.score['score']) - lose_score
                            p.score['win_score'] = "-%s" % lose_score
            p = Player(winner, self.bid, self.rid)
            p.score['score'] =  int(p.score['score']) + win_score
            p.score['win_score'] = win_score
            
        for uid in self.members:
            if not uid:
                continue
            p = Player(uid, self.bid, self.rid)
            # 重置玩家状态,和计算分数
            p_data = {"uid":uid, "win_score":p.score['win_score'], "score":p.score['score'], "white_bar":[], "pair":[], "out_card":[], "current_card":p.current_card.members, "dark_bar":p.dark_bar.members}
            if not winner:
                score = 0
                p_data['score'] = "0"
            else:
                score = int(p.score['score'])
            if dealer == uid:
                is_dealer = "y"
            else:
                is_dealer = "n"
            p_data['is_dealer'] = is_dealer
            db.update_player(self.rid, uid, score, 0)
            player_info = db.get_player(self.rid, uid)
            p_data['user_score'] = player_info['score']
            player_card.append(p_data)
        
        rules = {}
        #room_info = db.get_room(self.rid, self.bid)
        #gid = room_info.get("gid")
        gid = self.room['gid']
        if gid:
            rows = db.game_rule(gid)
        else:
            rows = db.room_rule(self.rid)
            gid = ""
        for row in rows:
            k = row['param']
            v = row['value']
            rules[k] = v
        
        #比赛的牌局统一规则
        game_type = self.room['game_type']
        match_id = self.room['mid']
        if match_id:
            if game_type == 'pdk':
                rules = {"must_put":"y", "release_duty":"y", "closed_double":"y"}
            else:
                rules = {"horse":0, "grab_bar_win":"y", "grab_bar_duty":"y", "bar_win_duty":"n", "seven_pair_win":"y"}
        else:
            match_id = ""
        
        game_round = int(self.room['game_round'])
        all_round = int(self.room['all_round'])
        mid = self.incr_mid()
        for uid in self.members:
            nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"match_id":match_id, "gid":gid, "rules":rules, "win_type":"", "from_dissmiss":from_dissmiss, "dealer":self.room['dealer'], "game_round":game_round, "player_card":player_card, "mid":mid, "act":"game_over", "winner":winner, "card":"", "rid":self.rid, "all_horse_card":[], "horse_card":[], "horse_num":0}})
            try:
                if winner == uid:
                    win_round = 1
                else:
                    win_round = 0
                if db.has_user_stat(self.bid, uid, game_type):
                    db.update_user_stat(self.bid, uid, game_type, win_round)
                else:
                    db.add_user_stat(self.bid, uid, game_type, win_round, 0)
            except:
                logging.error(u"统计用户生涯错误:%s" % uid, exc_info=True)
        logging.info(u"房间%s牌局%s第%s局结束" % (self.rid, game_type, game_round))
        if winner:
            self.room['dealer'] = winner
        
        self.room['status'] = 'over'
        self.room['stop_pop_user'] = ''
        self.room['last_put_user'] = ''
        self.room['last_get_card'] = ''
        self.room['last_put_type'] = ''
        self.room['last_get_point'] = ''
        
        db.game_over(self.rid, game_round)
        if match_id:
            nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"all_round":all_round, "match_id":match_id, "rules":rules, "win_type":"", "from_dissmiss":from_dissmiss,"dealer":self.room['dealer'], "game_round":self.room['game_round'], "player_card":player_card, "mid":mid, "act":"game_over", "winner":winner, "card":"", "rid":self.rid, "all_horse_card":[], "horse_card":[], "horse_num":0}}, "match_club")
        self.room['game_round'] = game_round + 1
        if all_round <= game_round:
            self.dismiss(act='room_over')
        else:
            if match_id:
                exp_time = (datetime.datetime.now() + datetime.timedelta(seconds=15)).strftime("%Y-%m-%d %H:%M:%S")
                db.add_cron(self.bid, "auto_ready", self.rid, 0, exp_time)
        
    def dismiss(self, act='room_over'):
        time.sleep(1)
        db = dao.Game_DB()
        player_data = {}
        player_stat = []
        if not self.room['status']:
            logging.info(u"房间结束,未开始:%s" % self.rid)
            deduct_flag = False
            winner = ""
            for uid in self.members:
                player_stat.append({"uid":uid,"horse":0,"dark_bar":0,"white_bar":0,"score":0,"win_num":0})
        else:
            p_stat = db.player_stat(self.rid)
            for ps in p_stat:
                ps['horse'] = int(ps['horse'])
                ps['dark_bar'] = int(ps['dark_bar'])
                ps['white_bar'] = int(ps['white_bar'])
                ps['score'] = int(ps['score'])
                ps['win_num'] = int(ps['win_num'])
                
                ps['max_score'] = int(ps['max_score'])
                ps['lose_num'] = int(ps['lose_num'])
                ps['bomb'] = int(ps['dark_bar'])
                player_data[str(ps['uid'])] = ps
            deduct_flag = True
            if p_stat:
                winner = p_stat[-1]['uid']
            else:
                winner = ""
            # 排序最后一家为大赢家
            player_stat = p_stat
         
        room_info = db.get_room(self.rid, self.bid)
        admin = room_info['admin']
        match_id = room_info['mid']
        gid = room_info['gid']
        if not gid:
            gid = 0
        for ps in player_stat:
            if ps['uid'] == winner:
                is_winner = 'y'
            else:
                is_winner = 'n'
            db.add_room_stat(match_id, gid, self.rid, ps['uid'], ps['score'], is_winner)
            
        if not match_id:
            #比赛的房间不发送room_over
            for uid in self.members:
                nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"act":"room_over", "rid":self.rid, "player_stat":player_stat, "winner":winner, "admin":admin}})
        else:
            #比赛房间不扣房卡
            deduct_flag = False
        db.dismiss_room(self.rid)
        game_type = self.room['game_type']
        gid = self.room['gid']
        if match_id or gid:
            nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"game_type":game_type, "match_id":match_id, "gid":gid, "act":"room_over", "rid":self.rid, "player_stat":player_stat, "winner":winner, "admin":admin}}, "match_club")
            
        if deduct_flag:
            card = room_info['card']
            db.deduct_card(self.bid, admin, card)
            nsq_pub({"act":"deduct_card", "bid":self.bid, "uid":admin, "card":card, "rid":self.rid}, "total")
            logging.info(u"房间%s解散成功,扣除房卡, bid:%s,uid:%s,card:%s" % (self.rid, self.bid, admin, card))
        else:
            logging.info(u"房间%s解散成功,游戏无需扣房卡" % self.rid)
        redisco.connection.delete("r:%s:current_card" % self.rid)
        redisco.connection.delete("r:%s:out_card" % self.rid)
        redisco.connection.delete("r:%s" % self.rid)
        redisco.connection.delete("r:%s:mid" % self.rid)
        redisco.connection.delete("r:%s:p" % self.rid)
        
    
if __name__ == "__main__":
    tdh = MaJiang('100016', 'szjt')
    tdh.pass_card('', '')
    

